V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
rimutuyuan
V2EX  ›  问与答

求解一个 Go 数组问题

  •  
  •   rimutuyuan · 2022-08-24 10:33:37 +08:00 · 1091 次点击
    这是一个创建于 816 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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

    9 条回复    2022-08-24 12:04:33 +08:00
    RoninZc
        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 底层实现
    RoninZc
        2
    RoninZc  
       2022-08-24 10:42:47 +08:00
    修改一下

    在 s= append(s, 2048) 执行后 s 被重新赋值 p 内数据为 0, 1, 2, 2048 ,len 为 4
    tianyou666shen
        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
    RoninZc
        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
    }
    ```
    fiypig
        5
    fiypig  
       2022-08-24 11:01:05 +08:00
    return s 就是你要的效果了
    rimutuyuan
        6
    rimutuyuan  
    OP
       2022-08-24 11:03:49 +08:00
    感谢各位大佬
    kkeep
        7
    kkeep  
       2022-08-24 11:52:19 +08:00 via Android
    你多看看 a tour of go 即可
    GP1
        9
    GP1  
       2022-08-24 12:04:33 +08:00
    你修改之后倒是 return 回去啊?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2865 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 14:36 · PVG 22:36 · LAX 06:36 · JFK 09:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.