golang基礎之數組

來源:互聯網
上載者:User

文章轉載請註明出處www.leexide.com
希望每一位尋求轉載的朋友都能夠按照要求進行,鼓勵原創,尊重原創。
公眾號:DevOps營運運營之家
QQ號碼:1045884038
E-mail:leexide@126.com
如有問題或建議,請關注公眾號

1 數組介紹

數組是同一類型元素的集合。例如,整數集合 5,8,9,79,76 形成一個數組。Go 語言中不允許混合不同類型的元素,例如包含字串和整數的數組。(註:當然,如果是 interface{} 類型數組,可以包含任意類型) 。

2 數組常見操作

一個數組的表示形式為 [n]Tn 表示數組中元素的數量,T 代表每個元素的類型。元素的數量 n 也是該類型的一部分 。

2.1 數組初始化

一維數組初始化如下

func main() {    var a [4]int    //元素自動初始化為零[0 0 0 0]    b := [4]int{2, 5}  //未提供初始化值得元素自動初始化為0  [2 5 0 0]    c := [4]int{5, 3: 10} //可指定索引位置初始化 [5 0 0 10]    d := [...]int{1, 2, 3} //編譯器按初始化值數量確定數組長度 [1 2 3]    e := [...]int{10, 3: 100} //支援索引初始化,但注意數組長度與此有關 [10 0 0 100]    fmt.Println(a, b, c, d, e)}

對於結構等複合類型,可省略元素初始化類型標籤

package mainimport "fmt"func main() {    type user struct {        name string        age  byte    }    d := [...]user{        {"tom", 20},// 可省略元素類型。        {"lee", 18},// 別忘了最後一行的逗號。    }    fmt.Printf("%#v\n", d)}/*output[2]main.user{main.user{name:"tom", age:0x14}, main.user{name:"lee", age:0x12}}*/

在定義多維陣列時,僅第一維度允許使用“...”

package mainimport "fmt"func main() {    a := [2][2]int{        {1, 2},        {3, 4},    }    b := [...][2]int{        {10, 20},        {30, 40},    }    c := [...][2][2]int{   //三維數組        {            {1, 2},            {3, 4},        },        {            {10, 20},            {30, 40},        },    }    fmt.Println(a)  //[[1 2] [3 4]]    fmt.Println(b)  //[[10 20] [30 40]]    fmt.Println(c)  //[[[1 2] [3 4]] [[10 20] [30 40]]]}

多維陣列定義

package mainimport (    "fmt")var arr0 [5][3]intvar arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}func main() {    a := [2][3]int{{1, 2, 3}, {4, 5, 6}}    b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 緯度不能用 "..."。    fmt.Println(arr0, arr1)    fmt.Println(a, b)}/*output[[0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0]] [[1 2 3] [7 8 9]][[1 2 3] [4 5 6]] [[1 1] [2 2] [3 3]] */

2.2 數組索引

數組的索引從 0 開始到 length - 1 結束

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)}

2.3 數組是實值型別

Go 中的數組是實值型別而不是參考型別。這意味著當數組賦值給一個新的變數時,該變數會得到一個原始數組的一個副本。如果對新變數變更,則不會影響原始數組。

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)  //a is  [USA China India Germany France]    fmt.Println("b is ", b)  //b is  [Singapore China India Germany France]}

上述程式中,a 的副本被賦給 b。在第 4 行中,b 的第一個元素改為 Singapore。這不會在原始數組 a 中反映出來。

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

package mainimport "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)}/*outputbefore passing to function  [5 6 7 8 8]inside function  [55 6 7 8 8]after passing to function  [5 6 7 8 8]*/

在上述程式的 13 行中, 數組 num 實際上是通過值傳遞給函數 changeLocal,數組不會因為函數調用而改變。

值拷貝行為會造成效能問題,通常會建議使用 slice,或數組指標。

package mainimport (    "fmt")func test(x [2]int) {    fmt.Printf("x: %p\n", &x)    x[1] = 1000}func main() {    a := [2]int{}    fmt.Printf("a: %p\n", &a)    test(a)    fmt.Println(a)}/*output:a: 0xc042062080x: 0xc0420620c0[0 0] */

2.4 數組長度和元素數量

通過將數組作為參數傳遞給 len 函數,可以得到數組的長度。 cap可以得到元素數量

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

注意:內建函數len和cap都返回第一維度長度

package mainfunc main() {    a := [2]int{}    b := [...][2]int{        {10, 20},        {30, 40},        {50, 60},    }    println(len(a), cap(a))   // 2 2    println(len(b), cap(b))   // 3 3    println(len(b[1]), cap(b[1]))  // 2 2}

####2.5 使用 range 迭代數組

for 迴圈可用於遍曆數組中的元素。

package mainimport "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])    }}

上面的程式使用 for 迴圈遍曆數組中的元素,從索引 0 到 length of the array - 1

Go 提供了一種更好、更簡潔的方法,通過使用 for 迴圈的 range 方法來遍曆數組。range返回索引和該索引處的值。讓我們使用 range 重寫上面的代碼。我們還可以擷取數組中所有元素的總和。

package mainimport "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 i, v := range a 利用的是 for 迴圈 range 方式。 它將返回索引和該索引處的值。 我們列印這些值,並計算數組 a 中所有元素的總和。

如果你只需要值並希望忽略索引,則可以通過用 _ 空白標識符替換索引來執行。

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

上面的 for 迴圈忽略索引,同樣值也可以被忽略。

2.6 數組操作符操作

如元素類型支援"==,!="操作符,那麼數組也支援此操作

package mainfunc main() {    var a, b [2]int    println(a == b)  //true    c := [2]int{1, 2}    d := [2]int{0, 1}    println(c != d) //true    /*        var e, f [2]map[string]int        println(e == f)  //invalid operation: e == f ([2]map[string]int cannot be compared)    */}

3 數組進階用法

3.1 多維陣列

到目前為止我們建立的數組都是一維的,Go 語言可以建立多維陣列。

package mainimport (    "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)}/*outputlion tiger cat dog pigeon peacock apple samsung microsoft google AT&T T-Mobile */

多維陣列遍曆

package mainimport (    "fmt")func main() {    var f [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}    for k1, v1 := range f {        for k2, v2 := range v1 {            fmt.Printf("(%d,%d)=%d ", k1, k2, v2)        }        fmt.Println()    }}/*output:(0,0)=1 (0,1)=2 (0,2)=3 (1,0)=7 (1,1)=8 (1,2)=9  */

3.2 數組指標和指標數組

要分清指標數組和數組指標的區別。指標數組是指元素為指標類型的數組,數組指標是擷取陣列變數的地址。

package mainimport "fmt"func main() {    x, y := 10, 20    a := [...]*int{&x, &y}    p := &a    fmt.Printf("%T,%v\n", a, a)  //[2]*int,[0xc042062080 0xc042062088]    fmt.Printf("%T,%v\n", p, p)  //*[2]*int,&[0xc042062080 0xc042062088]}

可擷取任意元素地址

func main() {    a := [...]int{1, 2}    println(&a, &a[0], &a[1])  //0xc042049f68 0xc042049f68 0xc042049f70}

數組指標可以直接用來操作元素

func main() {    a := [...]int{1, 2}    p := &a    p[1] += 10    println(p[1])   //12}

4 數組使用常見坑

定義數群組類型時,數組長度必須是非負整型常量運算式,長度是類型組成部分。也就是說,元素類型相同,但長度不同的數組不屬於同一類型。

例子:

func main() {    var d1 [3]int    var d2 [2]int    d1 = d2 //cannot use d2 (type [2]int) as type [3]int in assignment}

5 數組總結

  1. 數組:是同一種資料類型的固定長度的序列。

  2. 數組定義:var a [len]int,比如:var a [5]int,數組長度必須是常量,且是類型的組成部分。一旦定義,長度不能變。

  3. 長度是數群組類型的一部分,因此,var a[5] intvar a[10]int是不同的類型。

  4. 數組可以通過下標進行訪問,下標是從0開始,最後一個元素下標是:len-1。數組索引常用操作如下:

    for i := 0; i < len(a); i++ {   ...} for index, v := range a {   ...} 
  5. 訪問越界,如果下標在數組合法範圍之外,則觸發訪問越界,會panic

  6. 數組是實值型別,賦值和傳參會複製整個數組,而不是指標。因此改變副本的值,不會改變本身的值。

  7. 支援 "=="、"!=" 操作符,因為記憶體總是被初始化過的。

  8. 指標數組 [n]*T,數組指標*[n]T
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.