数组 Array
数组 Array
Golang Array 和以往认知的数组有很大不同。
1. 数组:是同一种数据类型的固定长度的序列。
2. 数组定义:var a [len]int,比如:var a [5]int,数组长度必须是常量,且是类型的组成部分。一旦定义,长度不能变。
3. 长度是数组类型的一部分,因此,var a[5] int和var 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
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
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
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
2
3
4
5
6
7
8
9
10
11
12
13
14
输出结果:
a: 0xc42007c010
x: 0xc42007c030
[0 0]
1
2
3
2
3
内置函数 len 和 cap 都返回数组长度 (元素数量)。
package main
func main() {
a := [2]int{}
println(len(a), cap(a))
}
1
2
3
4
5
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
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
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
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
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18