func main() {
var s []int
for i := 0; i < 3; i++ {
s = append(s, i)
}
modifySlice(s)
fmt.Println(s)
}
func modifySlice(s []int) {
s = append(s, 2048)
s[0] = 1024
}
输出为什么是 1024 1 2 而不是 1024 1 2 2048
1
RoninZc 2022-08-24 10:41:25 +08:00
golang 函数值传递
slice 底层结构 { len:长度, cap: 底层数组长度, *p 指针} main 中的 slice 传递进 modifySlice ,实际是底层数组指针和长度信息的拷贝 在 s= append(s, 2048) 执行后 s 被重新赋值 p 内数据为 1, 2, 3, 2048 ,len 为 4 其后 0 号位置被修改为 1024 ,其中 s 没有被返回 执行结束后,main 函数中的 s 与 modifySlice 共享底层数组,所以 0 号位置 被修改为哦 1024 但长度信息没有被修改 所以只显示 1024 1 2 建议看看 slice 底层实现 |
2
RoninZc 2022-08-24 10:42:47 +08:00
修改一下
在 s= append(s, 2048) 执行后 s 被重新赋值 p 内数据为 0, 1, 2, 2048 ,len 为 4 |
3
tianyou666shen 2022-08-24 10:54:25 +08:00
楼上说的对的 主要就是两点
1.go 里面的赋值是复制一份变量 2.slice 底层数组相同时,修改值会影响所有引用此数组的切片数据 main 函数中的 slice,长度是 3,开始是[0,1,2] modify 修改时,用相同底层数组复制了一份 slice,然后新的 slice append 后长度变为 3+1=4,随后修改 0 索引的底层数组值,此时底层数组为[1024,1,2,2048] 然后返回 main,此时长度还是 3,所以仅能够访问底层数组的前三个位置,打印显示[1024,1,2],如果要显示后面的 2048,需要将 slice 的长度+1 |
4
RoninZc 2022-08-24 10:59:09 +08:00
还有,上述示例中未考虑到 modifySlice 执行过程中 slice 扩容的情况
如果发生扩容 其后的修改都将指向的是新创建的 slice ,对 main 函数中的 slice 将毫无影响 所以一般这种情况推荐 modifySlice 函数中将 slice 返回,在 main 中重新赋值 ``` func main() { var s []int for i := 0; i < 3; i++ { s = append(s, i) } s = modifySlice(s) fmt.Println(s) } func modifySlice(s []int) []int { s = append(s, 2048) s[0] = 1024 return s } ``` |
5
fiypig 2022-08-24 11:01:05 +08:00
return s 就是你要的效果了
|
6
rimutuyuan OP 感谢各位大佬
|
7
kkeep 2022-08-24 11:52:19 +08:00 via Android
你多看看 a tour of go 即可
|
8
Erroad 2022-08-24 11:58:21 +08:00
|
9
GP1 2022-08-24 12:04:33 +08:00
你修改之后倒是 return 回去啊?
|