Golang基礎之數組

1 數組介紹數組

數組是同一類型元素的集合。例如,整數集合 5,8,9,79,76 造成一個數組。Go 語言中不容許混合不一樣類型的元素,例如包含字符串和整數的數組。(注:固然,若是是 interface{} 類型數組,能夠包含任意類型) 。app

2 數組常見操做ide

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

2.1 數組初始化oop

一維數組初始化以下性能

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

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

package maingoogle

import "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 main

import "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 main

import (
    "fmt"
)

var arr0 [5][3]int
var 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 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)
}

/*output
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]
*/


在上述程序的 13 行中, 數組 num 其實是經過值傳遞給函數 changeLocal,數組不會由於函數調用而改變。

值拷貝行爲會形成性能問題,一般會建議使用 slice,或數組指針。

package main

import (
    "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: 0xc042062080
x: 0xc0420620c0
[0 0]
 */


2.4 數組長度和元素數量

經過將數組做爲參數傳遞給 len 函數,能夠獲得數組的長度。 cap能夠獲得元素數量

package main

import "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 main

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

上面的程序使用 for 循環遍歷數組中的元素,從索引 0 到 length of the array - 1

Go 提供了一種更好、更簡潔的方法,經過使用 for 循環的 range 方法來遍歷數組。range返回索引和該索引處的值。讓咱們使用 range 重寫上面的代碼。咱們還能夠獲取數組中全部元素的總和。

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 i, v := range a 利用的是 for 循環 range 方式。 它將返回索引和該索引處的值。 咱們打印這些值,並計算數組 a 中全部元素的總和。

若是你只須要值並但願忽略索引,則能夠經過用 _ 空白標識符替換索引來執行。

for _, v := range a { // ignores index  }
1
上面的 for 循環忽略索引,一樣值也能夠被忽略。

2.6 數組操做符操做

如元素類型支持」==,!=」操做符,那麼數組也支持此操做

package main

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

/*output
lion tiger 
cat dog 
pigeon peacock 

apple samsung 
microsoft google 
AT&T T-Mobile 
*/



多維數組遍歷

package main

import (
    "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 main

import "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 數組總結

數組:是同一種數據類型的固定長度的序列。

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

長度是數組類型的一部分,所以,var a[5] int和var a[10]int是不一樣的類型。

數組能夠經過下標進行訪問,下標是從0開始,最後一個元素下標是:len-1。數組索引經常使用操做以下:

for i := 0; i < len(a); i++ {
   ...

for index, v := range a {
   ...


訪問越界,若是下標在數組合法範圍以外,則觸發訪問越界,會panic

數組是值類型,賦值和傳參會複製整個數組,而不是指針。所以改變副本的值,不會改變自己的值。

支持 「==」、」!=」 操做符,由於內存老是被初始化過的。

指針數組 [n]*T,數組指針*[n]T。  

相關文章
相關標籤/搜索