参考的文章

OverNote-Golang
Golang-100-Days-数组

1.1 什么是数组

Go语言提供了数组类型的数据结构,数组是具有相同类型的一组已编号且长度固定的数据项序列,这种类型可以是任意原始类型,例如整形/字符串/自定义类型
数组元素可以通过索引来读取(从0开始)
数组一旦定义后,大小不能更改。

1.2 声明和初始化数组

需要指明数组的大小和存储的数据类型

  1. var balance [10]float32
  2. var balance = [5]float32{10000.0,2.0,3.4,7.0,50.0}

初始化中的{}元素个数不能大于[]中的数字。如果忽略[]中的数字不设置数组大小,Go会根据元素的个数设置数组大小

  1. var balance = []float32{1000.0, 2.0, 3.4, 7.0, 50.0}

数组的其他创建方式:

  1. var a [4]float32 // 定义,但不初始化
  2. var b = [5]string{"a", "b"} // 5个空间,后面不足的用默认值填充
  3. var c = [5]int{'A', 'B', 'C', 'D', 'E'} // 存的是byte
  4. d := [...] int{1, 2, 3, 4, 5} // 自动设置数组的大小,这其实变化成了切片
  5. e := [5] int32{2: 10, 4: 11} // 根据索引有选择的初始化,没选择的使用默认值
  6. fmt.Println(a, b, c, d, e)
  7. /*
  8. [0 0 0 0] [a b ] [65 66 67 68 69] [1 2 3 4 5] [0 0 10 0 11]
  9. */

数组访问跟其他语言一样直接变量名加索引即可

  1. a := [5]int32{1, 3, 4, 5}
  2. b := a[3] // 5
  3. fmt.Println(a, b)

数组的长度,可以通过len()函数获取

  1. a := [5]int32{1, 2, 3, 4}
  2. b := len(a) // 5,因为长度已经初始化给出了
  3. c := [...]int32{1, 2, 3, 4}
  4. d := len(c) // 4
  5. fmt.Println(b, d)

遍历数组,可以使用原始的方法进行遍历,通过len()确定遍历长度

  1. a := [...]int32{1, 2, 3, 4, 5}
  2. for i := 0; i < len(a); i++ {
  3. fmt.Println(a[i])
  4. }

第二种遍历方法就是通过range进行遍历

  1. b := [...]int32{1, 2, 4, 5, 6}
  2. for k, v := range b {
  3. fmt.Printf("index: %v,value:%v\n", k, v)
  4. }
  5. // 如果不想要其中的key,可以使用缺省定义符号_
  6. c := [...]int32{1, 2, 4, 5, 6}
  7. for _, v := range c {
  8. fmt.Printf("value:%v\n", v)
  9. }
  10. // 也可以直接获取索引,然后获取值
  11. for i := range c {
  12. fmt.Println("Array item", i, "is", c[i])
  13. }

1.3 多维数组定义

  1. //定义一个3行4列的二维数组,如果某位置没有赋值,就使用默认值
  2. a := [3][4]int32{{1, 2, 3, 4}, {5, 6, 7}, {10, 11}} // 注意最外层的大括号
  3. for i := 0; i < len(a); i++ {
  4. fmt.Println(a[i])
  5. }
  6. /*
  7. [1 2 3 4]
  8. [5 6 7 0]
  9. [10 11 0 0]
  10. */

1.4 数组是值类型

数组是值类型,Go中的数组是值类型,而不是引用类型,这意味着当它们被分配给一个新变量时,将把原始数组的副本分配给新变量。如果对新变量进行了更改,则不会在原始数组中反应。

  1. a := [...]string{"USA", "China", "India", "Germany", "France"}
  2. b := a // a copy of a is assigned to b
  3. b[0] = "Singapore"
  4. fmt.Println("a is ", a)
  5. fmt.Println("b is ", b)
  6. /*
  7. a is [USA China India Germany France]
  8. b is [Singapore China India Germany France]
  9. */

1.5 不同定义的区别

  1. var arr1 = new([5]int)
  2. var arr2 [5]int

上面两种定义方式,arr1的类型是*[5]int,而arr2得类型是[5]int。这样的结果就是把一个数组赋值给另一个时,需要在做一次数组内存的拷贝操作,例如:

  1. arr2: = *arr1
  2. arr2[2] = 100

这样两个数组就有了相同的值,在赋值后需改rr2不会对arr1生效,所以在函数中数组作为参数参入时,如func1(arr2),会产生一次数组拷贝,func1方法不会修改原始的数组arr2,如果想修改原数组,那么arr2必须通过&操作符以引用的方式传过来,例如func1(&arr2),示例:

  1. func main() {
  2. a := [5]int{1, 2, 3, 4, 5}
  3. arrF3(a)
  4. fmt.Println(a)
  5. b := [5]int{1, 2, 3, 4, 5}
  6. arrF4(&b)
  7. fmt.Println(b)
  8. }
  9. func arrF3(arr [5]int) {
  10. arr[1] = 200
  11. }
  12. func arrF4(arr *[5]int) {
  13. (*arr)[1] = 200
  14. }
  15. /*
  16. [1 2 3 4 5]
  17. [1 200 3 4 5]
  18. */

2.1 多维数组

数组通常是以为的,但是可以用来组装成多维数组例如:[3][5]int,[2][2][2]float64等。
示例:

  1. func main() {
  2. var table [WIDTH][HEIGHT] int
  3. for y := 0; y < WIDTH; y++ {
  4. for x := 0; x < HEIGHT; x++ {
  5. table[x][y] = (x + 1) * (y + 1)
  6. }
  7. }
  8. // 遍历方式一
  9. for i := 0; i < WIDTH; i++ {
  10. for j := 0; j < HEIGHT; j++ {
  11. fmt.Printf("%d%s", table[i][j], "\t")
  12. }
  13. fmt.Println("")
  14. }
  15. fmt.Println("***************************")
  16. // 遍历方式二
  17. for _, v := range table {
  18. for _, v2 := range v {
  19. fmt.Printf("%d%s", v2, "\t")
  20. }
  21. fmt.Println("")
  22. }
  23. }
  24. /*
  25. 1 2 3 4
  26. 2 4 6 8
  27. 3 6 9 12
  28. 4 8 12 16
  29. ***************************
  30. 1 2 3 4
  31. 2 4 6 8
  32. 3 6 9 12
  33. 4 8 12 16
  34. */