1. 数组Array

Golang Array和以往认知的数组有很大不同。

  1. 1. 数组:是同一种数据类型的固定长度的序列。
  2. 2. 数组定义:var a [len]int,比如:var a [5]int,数组长度必须是常量,且是类型的组成部分。一旦定义,长度不能变。
  3. 3. 长度是数组类型的一部分,因此,var a[5] intvar a[10]int是不同的类型。
  4. 4. 数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1
  5. for i := 0; i < len(a); i++ {
  6. }
  7. for index, v := range a {
  8. }
  9. 5. 访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic
  10. 6. 数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值。
  11. 7.支持 "==""!=" 操作符,因为内存总是被初始化过的。
  12. 8.指针数组 [n]*T,数组指针 *[n]T

1.1.1. 数组初始化:

一维数组:

  1. 全局:
  2. var arr0 [5]int = [5]int{1, 2, 3}
  3. var arr1 = [5]int{1, 2, 3, 4, 5}
  4. var arr2 = [...]int{1, 2, 3, 4, 5, 6}
  5. var str = [5]string{3: "hello world", 4: "tom"}
  6. 局部:
  7. a := [3]int{1, 2} // 未初始化元素值为 0。
  8. b := [...]int{1, 2, 3, 4} // 通过初始化值确定数组长度。
  9. c := [5]int{2: 100, 4: 200} // 使用索引号初始化元素。
  10. d := [...]struct {
  11. name string
  12. age uint8
  13. }{
  14. {"user1", 10}, // 可省略元素类型。
  15. {"user2", 20}, // 别忘了最后一行的逗号。
  16. }

代码:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. var arr0 [5]int = [5]int{1, 2, 3}
  6. var arr1 = [5]int{1, 2, 3, 4, 5}
  7. var arr2 = [...]int{1, 2, 3, 4, 5, 6}
  8. var str = [5]string{3: "hello world", 4: "tom"}
  9. func main() {
  10. a := [3]int{1, 2} // 未初始化元素值为 0。
  11. b := [...]int{1, 2, 3, 4} // 通过初始化值确定数组长度。
  12. c := [5]int{2: 100, 4: 200} // 使用引号初始化元素。
  13. d := [...]struct {
  14. name string
  15. age uint8
  16. }{
  17. {"user1", 10}, // 可省略元素类型。
  18. {"user2", 20}, // 别忘了最后一行的逗号。
  19. }
  20. fmt.Println(arr0, arr1, arr2, str)
  21. fmt.Println(a, b, c, d)
  22. }

输出结果:

  1. [1 2 3 0 0] [1 2 3 4 5] [1 2 3 4 5 6] [ hello world tom]
  2. [1 2 0] [1 2 3 4] [0 0 100 0 200] [{user1 10} {user2 20}]

多维数组

  1. 全局
  2. var arr0 [5][3]int
  3. var arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
  4. 局部:
  5. a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
  6. b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 纬度不能用 "..."。

代码:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. var arr0 [5][3]int
  6. var arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
  7. func main() {
  8. a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
  9. b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 纬度不能用 "..."。
  10. fmt.Println(arr0, arr1)
  11. fmt.Println(a, b)
  12. }

输出结果:

  1. [[0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0]] [[1 2 3] [7 8 9]]
  2. [[1 2 3] [4 5 6]] [[1 1] [2 2] [3 3]]

值拷贝行为会造成性能问题,通常会建议使用 slice,或数组指针。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func test(x [2]int) {
  6. fmt.Printf("x: %p\n", &x)
  7. x[1] = 1000
  8. }
  9. func main() {
  10. a := [2]int{}
  11. fmt.Printf("a: %p\n", &a)
  12. test(a)
  13. fmt.Println(a)
  14. }

输出结果:

  1. a: 0xc42007c010
  2. x: 0xc42007c030
  3. [0 0]

内置函数 len 和 cap 都返回数组长度 (元素数量)。

  1. package main
  2. func main() {
  3. a := [2]int{}
  4. println(len(a), cap(a))
  5. }

输出结果:

  1. 2 2

多维数组遍历:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. var f [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
  7. for k1, v1 := range f {
  8. for k2, v2 := range v1 {
  9. fmt.Printf("(%d,%d)=%d ", k1, k2, v2)
  10. }
  11. fmt.Println()
  12. }
  13. }

输出结果:

  1. (0,0)=1 (0,1)=2 (0,2)=3
  2. (1,0)=7 (1,1)=8 (1,2)=9

1.1.2. 数组拷贝和传参

  1. package main
  2. import "fmt"
  3. func printArr(arr *[5]int) {
  4. arr[0] = 10
  5. for i, v := range arr {
  6. fmt.Println(i, v)
  7. }
  8. }
  9. func main() {
  10. var arr1 [5]int
  11. printArr(&arr1)
  12. fmt.Println(arr1)
  13. arr2 := [...]int{2, 4, 6, 8, 10}
  14. printArr(&arr2)
  15. fmt.Println(arr2)
  16. }

1.1.3. 数组练习

求数组所有元素之和

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "time"
  6. )
  7. // 求元素和
  8. func sumArr(a [10]int) int {
  9. var sum int = 0
  10. for i := 0; i < len(a); i++ {
  11. sum += a[i]
  12. }
  13. return sum
  14. }
  15. func main() {
  16. // 若想做一个真正的随机数,要种子
  17. // seed()种子默认是1
  18. //rand.Seed(1)
  19. rand.Seed(time.Now().Unix())
  20. var b [10]int
  21. for i := 0; i < len(b); i++ {
  22. // 产生一个0到1000随机数
  23. b[i] = rand.Intn(1000)
  24. }
  25. sum := sumArr(b)
  26. fmt.Printf("sum=%d\n", sum)
  27. }

找出数组中和为给定值的两个元素的下标,例如数组[1,3,5,8,7],找出两个元素之和等于8的下标分别是(0,4)和(1,2)

  1. package main
  2. import "fmt"
  3. // 找出数组中和为给定值的两个元素的下标,例如数组[1,3,5,8,7],
  4. // 找出两个元素之和等于8的下标分别是(0,4)和(1,2)
  5. // 求元素和,是给定的值
  6. func myTest(a [5]int, target int) {
  7. // 遍历数组
  8. for i := 0; i < len(a); i++ {
  9. other := target - a[i]
  10. // 继续遍历
  11. for j := i + 1; j < len(a); j++ {
  12. if a[j] == other {
  13. fmt.Printf("(%d,%d)\n", i, j)
  14. }
  15. }
  16. }
  17. }
  18. func main() {
  19. b := [5]int{1, 3, 5, 8, 7}
  20. myTest(b, 8)
  21. }