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

2021-11-07 14:47:50 +08:00
 yagamil
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
}

望大神指点。

806 次点击
所在节点    Go 编程语言
2 条回复
farmer001
2021-11-07 20:05:52 +08:00
你打印的是切片里引用的底层数据的地址,而不是切片本身的地址。实参和形参的切片是不同的切片,只不过它们引用的底层数据是一样的。
yagamil
2021-11-11 17:11:36 +08:00
@farmer001 谢谢大神回复。
如果按照你这样理解, fmt.Printf("%p\n", arr) , 这个取的并不是切片的指针地址,而且指向底层的地址?
如果要获取切片地址,要 fmt.Printf("%d" , &arr) 这样吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/813641

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX