数组 Array

数组 Array

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

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。
1
2
3
4
5
6
7
8
9
10
11
12

数组初始化:

一维数组:

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

多维数组

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)
    //[[0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0]] [[1 2 3] [7 8 9]]
    fmt.Println(a, b)
    //[[1 2 3] [4 5 6]] [[1 1] [2 2] [3 3]]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

值拷贝行为会造成性能问题,通常会建议使用 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)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

输出结果:

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

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

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

输出结果:

2 2
1

多维数组遍历:

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()
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

输出结果:

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

数组拷贝和传参

package main

import "fmt"

func printArr1(arr [3]int) {
	arr[0] = 10
	for i, v := range arr {
		fmt.Println(i, v)
	}
}
func printArr2(arr *[3]int) {
	arr[0] = 10
	for i, v := range arr {
		fmt.Println(i, v)
	}
}
func main() {
	var arr1 [3]int
	printArr1(arr1)
	fmt.Println(arr1)
	arr2 := [...]int{2, 2, 2}
	printArr2(&arr2)
	fmt.Println(arr2)
}
//数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值。
//但*[n]T数组指针则会改变值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

输出结果:

0 10
1 0
2 0
[0 0 0]
0 10
1 2
2 2
[10 2 2]
1
2
3
4
5
6
7
8

数组练习

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

package main
import "fmt"
func myTest(a [5]int, target int) {

    for i := 0; i < len(a); i++ {
        other := target - a[i]

        for j := i + 1; j < len(a); j++ {
            if a[j] == other {
                fmt.Printf("(%d,%d)\n", i, j)
            }
        }
    }
}
func main() {
    b := [5]int{1, 3, 5, 8, 7}
    myTest(b, 8)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18