4

求解一个 Go 数组问题

 2 years ago
source link: https://www.v2ex.com/t/874984
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  问与答

求解一个 Go 数组问题

  rimutuyuan · 38 分钟前 · 147 次点击
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

6 条回复    2022-08-24 11:03:49 +08:00
RoninZc

RoninZc      30 分钟前

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 底层实现
RoninZc

RoninZc      29 分钟前

修改一下

在 s= append(s, 2048) 执行后 s 被重新赋值 p 内数据为 0, 1, 2, 2048 ,len 为 4
tianyou666shen

tianyou666shen      17 分钟前

楼上说的对的 主要就是两点
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
RoninZc

RoninZc      12 分钟前

还有,上述示例中未考虑到 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
}
```
fiypig

fiypig      10 分钟前

return s 就是你要的效果了
rimutuyuan

rimutuyuan      8 分钟前

感谢各位大佬

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK