go学习笔记(11)切片(4)数组转换成切片及切片复制

IMG_6131.jpg

数组转切片

数组可以转换成切片,但是转换成切片后,新的切片和原来的数组共享同一块存储空间。

比如下面的代码:

1
2
3
4
5
6
7
8
a := [5]int{1, 2, 3, 4, 5}
b := a[:3]
c := a[3:]
a[0] = 22
a[4] = 33
fmt.Println("a:", a)
fmt.Println("b:", b)
fmt.Println("c:", c)

输出:

1
2
3
a: [22 2 3 4 33]
b: [22 2 3]
c: [4 33]

可以看到,a是一个有5个元素的数组,b,c分别是从a中用切片表达式产生的新切片,它们共享同一块存储空间,在使用的时候要注意这一点。

go语言中的数组用得真的不多,所以也很少有把数组转成切片的需求。

切片复制

通过切片表达式生成的切片会和原切片共享存储空间,如果我们想得到一个拥有同样的数据但不共享存储的切片,那就需要用到内置的copy函数了。

1
2
3
4
5
6
7
8
9
10
a := []int{1, 2, 3, 4, 5}
b := make([]int, 5)
cnt := copy(b, a)

a[0] = 0
b[1] = 6

fmt.Println("a:", a)
fmt.Println("b:", b)
fmt.Println("cnt:", cnt)

输出:

1
2
3
a: [0 2 3 4 5]
b: [1 6 3 4 5]
cnt: 5

copy函数将a中的数据复制到b中,两者不再共享内存。

copy函数的两个参数切片的容量不同时,它在复制到容量上限后停止并返回本次复制的数据个数:

1
2
3
4
5
6
a := []int{1, 2, 3}
b := make([]int, 2)
cnt := copy(b, a)
fmt.Println("a:", a)
fmt.Println("b", b)
fmt.Println("cnt:", cnt)

输出:

1
2
3
a: [1 2 3]
b [1 2]
cnt: 2

也可以从源切片的中间复制数据:

1
2
3
4
5
6
a := []int{1, 2, 3, 4, 5, 6}
b := make([]int, 2)
cnt := copy(b, a[3:])
fmt.Println("a:", a)
fmt.Println("b", b)
fmt.Println("cnt:", cnt)

输出:

1
2
3
a: [1 2 3 4 5 6]
b [4 5]
cnt: 2

copy 函数还支持两个共享底层数据的切片之间的复制:

1
2
3
4
a := []int{1, 2, 3, 4, 5, 6}
cnt := copy(a, a[3:])
fmt.Println("a:", a)
fmt.Println("cnt:", cnt)

输出:

1
2
a: [4 5 6 4 5 6]
cnt: 3

copy函数也可以用在数组中:

1
2
3
4
5
6
7
a := []int{1, 2, 3, 4, 5, 6}
b := [4]int{7, 8, 9, 10}
c := make([]int, 2)
copy(c, b[:])
fmt.Println("c:", c)
copy(b[:], a)
fmt.Println("b:", b)

输出

1
2
c: [7 8]
b: [1 2 3 4]

江达小记