最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文教你如何快速學會Go的切片和數組數據類型

 更新時間:2023年03月07日 09:46:07   作者:7small7  
數組是屬于同一類型的元素的集合。切片是數組頂部的方便、靈活且功能強大的包裝器。本文就來和大家聊聊Go中切片和數組的使用,需要的可以參考一下

什么是數組

數組是屬于同一類型的元素的集合。例如,整數 5、8、9、79、76 的集合形成一個數組。Go 中不允許混合不同類型的值,例如,同時包含字符串和整數的數組。

聲明數組

數組屬于類型 。 表示數組中的元素數,并表示每個元素的類型。元素的數量也是類型的一部分(我們稍后將對此進行更詳細的討論。[n]TnTn

有不同的方法來聲明數組。讓我們一個接一個地看一下。

package main

import (  
    "fmt"
)


func main() {  
    var a [3]int //int array with length 3
    fmt.Println(a)
}

var a [3]int 聲明一個長度為 3 的整數數組。數組中的所有元素都將自動分配數組類型的零值。在這種情況下是一個整數數組,因此的所有元素都賦給 ,int 的零值。運行上述程序將打印a a 0

[0 0 0]

數組的索引從 開始,到 結束于 。讓我們?yōu)樯厦娴臄到M分配一些值。0 length - 1。

package main

import (  
    "fmt"
)


func main() {  
    var a [3]int //int array with length 3
    a[0] = 12 // array index starts at 0
    a[1] = 78
    a[2] = 50
    fmt.Println(a)
}

a[0] 將值賦給數組的第一個元素。該程序將打印

[12 78 50]

讓我們使用短語法聲明創(chuàng)建相同的數組。

package main 

import (  
    "fmt"
)

func main() {
    // short hand declaration to create array
    a := [3]int{12, 78, 50} 
    fmt.Println(a)
}

上面的程序將打印相同的輸出:

[12 78 50]

在短語法聲明期間,不必為數組中的所有元素賦值。

package main

import (  
    "fmt"
)

func main() {  
    a := [3]int{12} 
    fmt.Println(a)
}

在上面的程序中,第 8 行聲明了一個長度為 3 的數組,但只提供了一個值 。其余 2 個元素將自動指定。此程序將打印a := [3]int{12} 12 0

[12 0 0]

您甚至可以忽略聲明中數組的長度,并將其替換為,并讓編譯器為您找到長度。這是在以下程序中完成的。...

package main

import (  
    "fmt"
)

func main() {
    // ... makes the compiler determine the length
    a := [...]int{12, 78, 50} 
    fmt.Println(a)
}

數組的大小是類型的一部分。因此 和 是不同的類型。因此,無法調整數組的大小。

package main

func main() {  
    a := [3]int{5, 78, 8}
    var b [5]int
    b = a 
    //not possible since [3]int and [5]int are distinct types
}

在上面程序的第 6 行中,我們嘗試將類型的變量分配給不允許的類型變量,因此編譯器將打印以下錯誤:

./prog.go:6:7: cannot use a (type [3]int) as type [5]int in assignment

數組是值類型

Go 中的數組是值類型,而不是引用類型。這意味著,當它們被分配給新變量時,原始數組的副本將分配給新變量。如果對新變量進行了更改,它將不會反映在原始數組中。

package main

import "fmt"

func main() {  
    a := [...]string{"USA", "China", "India", "Germany", "France"}
    b := a // a copy of a is assigned to b
    b[0] = "Singapore"
    fmt.Println("a is ", a)
    fmt.Println("b is ", b) 
}

上述代碼將打印出如下內容:

a is [USA China India Germany France]  
b is [Singapore China India Germany France]

同樣,當數組作為參數傳遞給函數時,它們按值傳遞,原始數組保持不變。

package main

import "fmt"

func changeLocal(num [5]int) {  
    num[0] = 55
    fmt.Println("inside function ", num)

}
func main() {  
    num := [...]int{5, 6, 7, 8, 8}
    fmt.Println("before passing to function ", num)
    changeLocal(num) //num is passed by value
    fmt.Println("after passing to function ", num)
}

在上面的第 13 行程序中,數組實際上是按值傳遞給函數的,因此不會因為函數調用而更改。該程序將打印:

before passing to function  [5 6 7 8 8]  
inside function  [55 6 7 8 8]  
after passing to function  [5 6 7 8 8]

數組的長度

通過將數組作為參數傳遞給函數(len)來找到數組的長度。

package main

import "fmt"

func main() {  
    a := [...]float64{67.7, 89.8, 21, 78}
    fmt.Println("length of a is",len(a))

}

上述程序將打?。?/p>

length of a is 4

迭代數組

使用for可用于循環(huán)訪問數組的元素。

package main

import "fmt"

func main() {  
    a := [...]float64{67.7, 89.8, 21, 78}
    for i := 0; i < len(a); i++ { //looping from 0 to the length of the array
        fmt.Printf("%d th element of a is %.2f\n", i, a[i])
    }
}

上面的程序使用循環(huán)來迭代數組的元素,從 index 到 。該程序有效并將打印:

0 th element of a is 67.70  
1 th element of a is 89.80  
2 th element of a is 21.00  
3 th element of a is 78.00

Go 提供了一種更好、更簡潔的方式,通過使用循環(huán)的范圍形式來迭代數組。 返回索引和該索引處的值。讓我們使用范圍重寫上面的代碼。我們還將找到數組中所有元素的總和。

package main

import "fmt"

func main() {  
    a := [...]float64{67.7, 89.8, 21, 78}
    sum := float64(0)
    for i, v := range a {//range returns both the index and value
        fmt.Printf("%d the element of a is %.2f\n", i, v)
        sum += v
    }
    fmt.Println("\nsum of all elements of a",sum)
}

上述程序的第 8 行是 for 循環(huán)的范圍形式。它將返回索引和該索引處的值。我們打印值,并計算數組中所有元素的總和。該程序的輸出是:

0 the element of a is 67.70  
1 the element of a is 89.80  
2 the element of a is 21.00  
3 the element of a is 78.00

sum of all elements of a 256.5

如果您只想要該值并希望忽略索引,則可以通過將索引替換為空白標識符來執(zhí)行此操作。_

for _, v := range a { //ignores index  
}

上面的 for 循環(huán)忽略了索引。同樣,該值也可以忽略。

多維數組

到目前為止,我們創(chuàng)建的數組都是單維的。可以創(chuàng)建多維數組。

package main

import (  
    "fmt"
)

func printarray(a [3][2]string) {  
    for _, v1 := range a {
        for _, v2 := range v1 {
            fmt.Printf("%s ", v2)
        }
        fmt.Printf("\n")
    }
}

func main() {  
    a := [3][2]string{
        {"lion", "tiger"},
        {"cat", "dog"},
        {"pigeon", "peacock"}, //this comma is necessary. The compiler will complain if you omit this comma
    }
    printarray(a)
    var b [3][2]string
    b[0][0] = "apple"
    b[0][1] = "samsung"
    b[1][0] = "microsoft"
    b[1][1] = "google"
    b[2][0] = "AT&T"
    b[2][1] = "T-Mobile"
    fmt.Printf("\n")
    printarray(b)
}

在上面的程序的第 17 行中,使用短手語法聲明了一個二維字符串數組。第 20 行末尾的逗號是必需的。這是因為詞法分析器根據簡單規(guī)則自動插入分號。另一個 2d 數組在第 23 行中聲明,并為每個索引逐個添加字符串。這是初始化 2d 數組的另一種方法。

第 7 行中的函數使用兩個 for 范圍循環(huán)來打印 2d 數組的內容。以上程序將打?。?/p>

lion tiger  
cat dog  
pigeon peacock 

apple samsung  
microsoft google  
AT&T T-Mobile

數組就是這樣。盡管數組似乎足夠靈活,但它們具有固定長度的限制。不能增加數組的長度。這就是切片進入畫面的地方。事實上,在 Go 中,切片比傳統(tǒng)數組更常見。

切片

切片是數組頂部的方便、靈活且功能強大的包裝器。切片本身不擁有任何數據。它們只是對現有數組的引用。

創(chuàng)建切片

具有 T 類型元素的切片由下式表示[]T

package main

import (  
    "fmt"
)

func main() {  
    a := [5]int{76, 77, 78, 79, 80}
    var b []int = a[1:4] //creates a slice from a[1] to a[3]
    fmt.Println(b)
}

該語法從一個數組開始從一個索引到另一個索引創(chuàng)建一個切片。因此,在上面程序的第 9 行中,從索引 1 到 3 創(chuàng)建數組的切片表示形式。使用該表達式:a[start:end]。

package main

import (  
    "fmt"
)

func main() {
    //creates and array and returns a slice reference
    c := []int{6, 7, 8} 
    fmt.Println(c)
}

在上面的函數的第 9 行中,創(chuàng)建一個包含 3 個整數的數組,并返回存儲在 c 中的切片引用。

修改切片

切片不擁有自己的任何數據。它只是基礎數組的表示形式。對切片所做的任何修改都將反映在基礎數組中。

package main

import (  
    "fmt"
)

func main() {  
    darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}
    dslice := darr[2:5]
    fmt.Println("array before",darr)
    for i := range dslice {
        dslice[i]++
    }
    fmt.Println("array after",darr) 
}

在上面程序的第 9 行中,我們從數組的索引 2、3、4 創(chuàng)建。for 循環(huán)將這些索引中的值遞增 1。當我們在for循環(huán)之后打印數組時,我們可以看到對切片的更改反映在數組中。程序的輸出是:

array before [57 89 90 82 100 78 67 69 59]  
array after [57 89 91 83 101 78 67 69 59]

當多個切片共享同一個基礎數組時,每個切片所做的更改將反映在數組中。

package main

import (  
    "fmt"
)

func main() {  
    numa := [3]int{78, 79 ,80}
    nums1 := numa[:] //creates a slice which contains all elements of the array
    nums2 := numa[:]
    fmt.Println("array before change 1",numa)
    nums1[0] = 100
    fmt.Println("array after modification to slice nums1", numa)
    nums2[1] = 101
    fmt.Println("array after modification to slice nums2", numa)
}

在第 9 行中,缺少開始值和結束值。“開始”和“結束”的默認值分別為 和 。兩個切片并共享同一個數組。程序的輸出是:

array before change 1 [78 79 80]  
array after modification to slice nums1 [100 79 80]  
array after modification to slice nums2 [100 101 80]

從輸出中可以清楚地看出,當切片共享同一個數組時。對切片所做的修改將反映在數組中。

切片長度和容量

切片的長度是切片中元素的數量。切片的容量是從創(chuàng)建切片的索引開始的基礎數組中的元素數。

package main

import (  
    "fmt"
)

func main() {  
    fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"}
    fruitslice := fruitarray[1:3]
    fmt.Printf("length of slice %d capacity %d", len(fruitslice), cap(fruitslice)) //length of fruitslice is 2 and capacity is 6
}

在上面的程序中,是從 的索引 1 和 2 創(chuàng)建的。因此,的長度為 2。

切片可以重新切片到其容量。超出此值的任何內容都將導致程序引發(fā)運行時錯誤。

package main

import (  
    "fmt"
)

func main() {  
    fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"}
    fruitslice := fruitarray[1:3]
    fmt.Printf("length of slice %d capacity %d\n", len(fruitslice), cap(fruitslice)) //length of is 2 and capacity is 6
    fruitslice = fruitslice[:cap(fruitslice)] //re-slicing furitslice till its capacity
    fmt.Println("After re-slicing length is",len(fruitslice), "and capacity is",cap(fruitslice))
}

在上述程序的第11行中,被重新切片到其容量。以上程序輸出:

length of slice 2 capacity 6  
After re-slicing length is 6 and capacity is 6

使用make創(chuàng)建切片

生成切片可以使用make([]T, len, cap)來創(chuàng)建切片。[]T表示數據類型、len表示切片長度、cap表示切片容量。make 函數創(chuàng)建一個數組并返回對它的切片引用。

package main

import (  
    "fmt"
)

func main() {  
    i := make([]int, 5, 5)
    fmt.Println(i)
}

默認情況下,使用 make 創(chuàng)建切片時,這些值將清零。上述程序將輸出 。[0 0 0 0 0]

切片追加

正如我們已經知道的那樣,數組被限制為固定長度,并且它們的長度不能增加。切片是動態(tài)的,可以使用函數將新元素追加到切片中。追加函數的定義是 。append([]T, x...):[]T。返回的是一個新的切片。

x ...函數定義中的 T 表示函數接受參數 x 的可變數量的參數。這些類型的函數稱為可變參數函數

不過,有一個問題可能會困擾您。如果切片由數組支持,并且數組本身具有固定長度,那么切片如何具有動態(tài)長度。在引擎蓋下發(fā)生的事情是,當新元素追加到切片時,將創(chuàng)建一個新數組?,F有數組的元素將復制到此新數組,并返回此新數組的新切片引用。新切片的容量現在是舊切片的兩倍。以下程序將使事情變得清晰。

package main

import (  
    "fmt"
)

func main() {  
    cars := []string{"Ferrari", "Honda", "Ford"}
    fmt.Println("cars:", cars, "has old length", len(cars), "and capacity", cap(cars)) //capacity of cars is 3
    cars = append(cars, "Toyota")
    fmt.Println("cars:", cars, "has new length", len(cars), "and capacity", cap(cars)) //capacity of cars is doubled to 6
}

在上面的程序中,容量最初為 3。我們將新元素附加到第 10 行中的汽車,并將 返回的切片再次分配給汽車?,F在,汽車的容量翻了一番,變成了6輛。上述程序的輸出是:

cars: [Ferrari Honda Ford] has old length 3 and capacity 3  
cars: [Ferrari Honda Ford Toyota] has new length 4 and capacity 6

切片類型的零值為 。切片的長度和容量為 0??梢允褂米芳雍瘮祵⒅底芳拥角衅?。

package main

import (  
    "fmt"
)

func main() {  
    var names []string //zero value of a slice is nil
    if names == nil {
        fmt.Println("slice is nil going to append")
        names = append(names, "John", "Sebastian", "Vinay")
        fmt.Println("names contents:",names)
    }
}

在上面的程序中為 nil,我們已將 3 個字符串附加到 。程序的輸出是:

slice is nil going to append  
names contents: [John Sebastian Vinay]

也可以使用運算符將一個切片追加到另一個切片。

package main

import (  
    "fmt"
)

func main() {  
    veggies := []string{"potatoes","tomatoes","brinjal"}
    fruits := []string{"oranges","apples"}
    food := append(veggies, fruits...)
    fmt.Println("food:",food)
}

在上述程序的第 10 行中,通過附加到切片中。程序的輸出是:

fruitsveggiesfood: [potatoes tomatoes brinjal oranges apples]

切片作為函數參數

可以將切片視為由結構類型在內部表示。

type slice struct {  
    Length        int
    Capacity      int
    ZerothElement *byte
}

切片包含長度、容量和指向數組第零個元素的指針。將切片傳遞給函數時,即使它按值傳遞,指針變量也將引用相同的基礎數組。因此,當切片作為參數傳遞給函數時,在函數內部所做的更改在函數外部也是可見的。讓我們編寫一個程序來檢查一下。

package main

import (  
    "fmt"
)

func subtactOne(numbers []int) {  
    for i := range numbers {
        numbers[i] -= 2
    }

}
func main() {  
    nos := []int{8, 7, 6}
    fmt.Println("slice before function call", nos)
    subtactOne(nos)                               //function modifies the slice
    fmt.Println("slice after function call", nos) //modifications are visible outside
}

上述程序第 17 行中的函數調用將切片的每個元素遞減 2。在函數調用后打印切片時,這些更改是可見的。如果您還記得,這與數組不同,在數組中,對函數內部的數組所做的更改在函數外部不可見。上述程序的輸出是

slice before function call [8 7 6]  
slice after function call [6 5 4]

多維切片

與數組類似,切片可以具有多個維度。

package main

import (  
    "fmt"
)


func main() {  
     pls := [][]string {
            {"C", "C++"},
            {"JavaScript"},
            {"Go", "Rust"},
            }
    for _, v1 := range pls {
        for _, v2 := range v1 {
            fmt.Printf("%s ", v2)
        }
        fmt.Printf("\n")
    }
}

輸出的結果是:

C C++  
JavaScript  
Go Rust

切片保存對基礎數組的引用。只要切片在內存中,就無法對數組進行垃圾回收。在內存管理方面,這可能會引起關注。讓我們假設我們有一個非常大的數組,我們只對處理其中的一小部分感興趣。從此以后,我們從該數組創(chuàng)建一個切片,并開始處理該切片。這里要注意的重要一點是,數組仍將在內存中,因為切片引用了它。

解決此問題的一種方法是使用 copy 函數來復制該切片。這樣,我們可以使用新的切片,并且可以對原始數組進行垃圾回收。copy(dst, src []T):int。

package main

import (  
    "fmt"
)

func countries() []string {  
    countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}
    neededCountries := countries[:len(countries)-2]
    countriesCpy := make([]string, len(neededCountries))
    copy(countriesCpy, neededCountries) //copies neededCountries to countriesCpy
    return countriesCpy
}
func main() {  
    countriesNeeded := countries()
    fmt.Println(countriesNeeded)
}

在上面程序的第 9 行中,創(chuàng)建一個禁止最后 2 個元素的切片。上述程序的第 11 行復制到下一行中的函數,并從中返回它。現在數組可以被垃圾回收,因為它不再被引用。

以上就是一文教你如何快速學會Go的切片和數組數據類型的詳細內容,更多關于Go切片 數組的資料請關注腳本之家其它相關文章!

相關文章

  • GO實現基于命令行的簡單IPS程序代碼

    GO實現基于命令行的簡單IPS程序代碼

    本文介紹了入侵防御系統(tǒng)IPS的工作原理和實現,IPS通過網絡流量監(jiān)控和實時響應,防止網絡攻擊,通過使用Go語言實現一個簡單的IPS示例程序,展示了如何獲取本地IP地址和探測網絡中其他設備的IP地址,包括如何定義和加載規(guī)則文件,以及如何檢測IP對相應端口的訪問是否達到規(guī)定閾值
    2024-12-12
  • Go語言TCP從原理到代碼實現詳解

    Go語言TCP從原理到代碼實現詳解

    這篇文章主要為大家介紹了Go語言TCP從原理到代碼實現詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • GO常見的錯誤99%程序員會遇到(解決方法)

    GO常見的錯誤99%程序員會遇到(解決方法)

    這篇文章主要介紹了GO常見的錯誤99%程序員會遇到,本文給出了解決方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-01-01
  • go語言中[]*int和*[]int的具體使用

    go語言中[]*int和*[]int的具體使用

    本文主要介紹了go語言中[]*int和*[]int的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • Golang中這些channel用法你了解嗎

    Golang中這些channel用法你了解嗎

    channel?是GO語言中一種特殊的類型,是連接并發(fā)goroutine的管道,這篇文章主要來和大家分享一下關于?nil?channel?通道,有緩沖通道,無緩沖通道的常用方法以及巧妙使用的方式,希望對大家有所幫助
    2023-08-08
  • Go語言單線程運行也會有的并發(fā)問題解析

    Go語言單線程運行也會有的并發(fā)問題解析

    這篇文章主要為大家介紹了Go語言單線程運行的并發(fā)問題解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • go語言LeetCode題解944刪列造序示例詳解

    go語言LeetCode題解944刪列造序示例詳解

    這篇文章主要為大家介紹了go語言LeetCode題解944刪列造序示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • Golang Map簡介以及底層原理

    Golang Map簡介以及底層原理

    這篇文章主要介紹了Golang Map簡介以及底層原理的相關資料,Go語言提供的map是一種鍵值對存儲結構,支持基本操作如len、delete等,map是非線程安全的,可用sync.Mutex確保并發(fā)安全,為高效查找和插入,需要的朋友可以參考下
    2024-10-10
  • Go語言計算指定年月天數的方法

    Go語言計算指定年月天數的方法

    這篇文章主要介紹了Go語言計算指定年月天數的方法,實例分析了Go語言操作時間的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 淺析Go語言中的緩沖區(qū)及其在fmt包中的應用

    淺析Go語言中的緩沖區(qū)及其在fmt包中的應用

    這篇文章主要為大家詳細介紹了Go語言中的緩沖區(qū)及其在fmt包中的應用的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2024-01-01

最新評論

寿宁县| 南漳县| 天镇县| 长武县| 科技| 浙江省| 双辽市| 陵川县| 集安市| 临汾市| 肇东市| 景东| 法库县| 铅山县| 昭平县| 亳州市| 同仁县| 手游| 石门县| 乐安县| 离岛区| 秭归县| 海淀区| 连城县| 平遥县| 阿勒泰市| 武宁县| 斗六市| 竹北市| 民县| 独山县| 龙州县| 白水县| 浙江省| 易门县| 霞浦县| 社旗县| 囊谦县| 尤溪县| 衡水市| 新疆|