切片赋值,实际上只是复制了地址:
b := a
b 引用了 a 的地址。因此,b 的任何修改,都会影响 a。
但是,如果 b 扩容了,b 就会新申请空间,把数据复制到新空间。b 与 a 就没啥关系了。
感觉 Golang 的这个设计真是很烂!因为我们在设计阶段无法预知两个切片操作是否共用一块内存,对变量 b 的操作是否对变量 a 产生副作用,设计阶段无法准确判定。在一款新型的程序设计语言中还会出现这样的“副作用”机制,让人感到很遗憾。
package main
import (
"fmt"
)
func main() {
a := []int{0, 1, 2, 3, 4}
b := a
b[0] = 111 //此处修改,a[0]同时修改
fmt.Println(a)
fmt.Println(b)
fmt.Println("---------------------")
b = append(b, 0) //b扩容后,不再与a共享内存
b[0] = 222 //此处修改,a[0]不受影响
fmt.Println(a)
fmt.Println(b)
fmt.Println("---------------------")
c := make([]int, len(a))
copy(c, a)
c[0] = 333 //此处修改,a[0]不受影响
fmt.Println(a)
fmt.Println(c)
}
>>运行结果:
C:/Users/Administrator/slice/slice.exe [C:/Users/Administrator/slice]
[111 1 2 3 4]
[111 1 2 3 4]
---------------------
[111 1 2 3 4]
[222 1 2 3 4 0]
---------------------
[111 1 2 3 4]
[333 1 2 3 4]
成功: 进程退出代码 0.
建议切片复制,还是用 copy 命令吧,直接复制数据,断绝关联。