go函数参数传递到底是值传递还是引用传递?

先说结果吧,重要的事情说N遍。

go函数全是值传递,没有引用传递!!!go函数全是值传递,没有引用传递!!!go函数全是值传递,没有引用传递!!!go函数全是值传递,没有引用传递!!!go函数全是值传递,没有引用传递!!!······

值传递

值传递(Pass by Value)是一种函数参数传递方式。在值传递中,当把变量作为参数传递给函数时,实际上传递的是变量的值的副本。这意味着在函数内部对参数的任何修改都不会影响到原始变量。值传递在函数调用时创建了原始数据的副本,因此函数内部的操作不会影响到原始数据。

引用传递

引用传递(Pass by Reference)是一种函数参数传递方式。在引用传递中,当把变量作为参数传递给函数时,实际上传递的是变量的内存地址(或者说引用)。这意味着在函数内部对参数的任何修改都会影响到原始变量,因为函数内部操作的是原始变量的地址。

主要有问题的就应该是slice,接下来会一步一步解析,slice作为函数参数时到底是什么传递

指针

形参和实际参数内存地址不一样,证明是值传递,由于形参和实参是指针,指向同一个变量。函数内对指针指向变量的修改,会修改原内容数据

func main() {
	var a int = 666
	b := &a
	fmt.Println("firstly",&b)
	getB(b)
	fmt.Println("thirdly",*b)
}

func getB(b *int){
	fmt.Println("secondly",&b)
	*b=888
}
firstly 0xc000006028
secondly 0xc000006038
thirdly 888

slice

形参和实际参数内存地址一样,不代表是引用类型

func main() {
	slice :=[]int{1,2,3,4}
	fmt.Printf("first:%p\n",slice)
	fmt.Println("second",slice,len(slice),cap(slice))
	getSlice(slice)
	fmt.Println("fifth",slice,len(slice),cap(slice))
}

func getSlice(slice []int){
	fmt.Printf("third:%p\n",slice)
	slice[0]=10
	slice=append(slice,5,6)
	fmt.Println("fourth",slice,len(slice),cap(slice))
}
first:0xc0000101e0
second [1 2 3 4] 4 4
third:0xc0000101e0
fourth [10 2 3 4 5 6] 6 8
fifth [10 2 3 4] 4 4

slice是一个结构体,他的第一个元素是一个指针类型,这个指针指向是底层数组的第一个元素,当参数是slice类型的时候,fmt.printf通过%p打印的slice变量的地址其实就是内部存储数组元素的地址,所以打印出来形参和实参内存地址一样。
因为slice作为参数时本质是传递的指针,上面证明了指针也是值传递,所以参数为slice也是值传递,指针指向的是同一个变量,函数对形参的修改,会修改原内容数据
单从slice这个结构体看,我们可以通过getSlice修改存储元素内容,但是永远修改不了len和cap,因为他们只是一个拷贝,如果要修改,那就要传递**&slice**作为参数才可以

你可能感兴趣的:(golang面试题,golang,开发语言,后端)