V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
yagamil
V2EX  ›  Go 编程语言

切片作为参数传参,使用 append 后在函数内切边被修改了,而在主函数里面没有被改变

  •  
  •   yagamil · 2021-11-07 14:47:50 +08:00 · 825 次点击
    这是一个创建于 1094 天前的主题,其中的信息可能已经有所发展或是发生改变。
    package main
    
    import "fmt"
    
    func main() {
            arr := make([]int, 3, 4)             //创建一个长度为 3 ,容量为 4 的切片
            fmt.Println(arr, len(arr), cap(arr)) //[0 0 0] 3 4
            // -----
            fmt.Printf("%p\n", arr)
            addNum(arr)
            // -----
            fmt.Println(arr, len(arr), cap(arr)) //[0 0 0] 3 4
            fmt.Printf("%p\n", arr)
    }
    
    func addNum(sli []int) {
            fmt.Printf("%p\n", sli)
            sli = append(sli, 4)
            fmt.Println(sli, len(sli), cap(sli)) //[0 0 0 4] 4 4
            fmt.Printf("%p\n", sli) 
    }
    
    

    看到网上的解释是, 在 addNum 里面,sli 的底层数组是的确被修改了,可是切片的 len 由于是值复制,所以切片的 len 没有被修改,导致外层 main 里面的切片没有被显示?

    如果是这样,那么应该传参的时候传入的切片地址应该不一样才对,因为是传值,传入的是切片结构体的拷贝值,而不应该是切片的原地址。

    type slice struct {
    	array unsafe.Pointer //存储数组指针
    	len   int
    	cap   int
    }
    

    望大神指点。

    farmer001
        1
    farmer001  
       2021-11-07 20:05:52 +08:00
    你打印的是切片里引用的底层数据的地址,而不是切片本身的地址。实参和形参的切片是不同的切片,只不过它们引用的底层数据是一样的。
    yagamil
        2
    yagamil  
    OP
       2021-11-11 17:11:36 +08:00
    @farmer001 谢谢大神回复。
    如果按照你这样理解, fmt.Printf("%p\n", arr) , 这个取的并不是切片的指针地址,而且指向底层的地址?
    如果要获取切片地址,要 fmt.Printf("%d" , &arr) 这样吗?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1077 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:59 · PVG 02:59 · LAX 10:59 · JFK 13:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.