1.14 Go 是值传递,还是引用传递、指针传递?¶
Golang中函数的参数为切片时是传引用还是传值?
对于这个问题,可能会有很多认为是传引用,就比如下面这段代码
func foo(s []int) {
s[0] = 666
}
func main() {
slice := []int{1,2}
fmt.Println(slice) // [1 2]
foo(slice)
fmt.Println(slice) // [666 2]
}
如果你不了解 Go 中切片的底层结构,你很可能会误信上面的观点。
但其实不是,Go语言中都是值传递,而不是引用传递,也不是指针传递。
Go 中切片的底层结构是这样的
type slice struct {
array unsafe.Pointer
len int
cap int
}
而当你将切片作为实参传给函数时,函数是会拷贝一份实参的结构和数据,生成另一个切片,实参切片和形参切片,不仅是长度、容量相等,连指向底层数组的指针都是一样的。
通过分别打印实参切片和形参切片的指针地址,就能验证这一观点
func foo(s []int) {
fmt.Printf("%p \n", &s) // 0xc00000c080
s = append(s, 666)
}
func main() {
slice := []int{1,2}
fmt.Printf("%p \n", &slice) // 0xc00000c060
foo(slice)
fmt.Printf("%p \n", &slice) // 0xc00000c060
}