【GO】 1.Go的参数传递都是值传递

在 Golang 中函数之间传递变量时总是以值的方式传递的,无论是 int,string,bool,array 这样的内置类型(或者说原始的类型),还是 slice,channel,map 这样的引用类型,在函数间传递变量时,都是以值的方式传递,也就是说传递的都是值的副本。

  • 1.int类型值传递的代码示例:

package main

import (
	"fmt"
)

func main() {
	var num int = 5
	fmt.Printf("%d\n", num)
	changeint(num)
	fmt.Printf("%d\n", num)
}

func changeint(num int) {
	num = 10
	fmt.Printf("%d\n", num)
}

结果:

5

10

5

可以看出来函数内对数组的修改并没有改变数组的值。

  • 2.切片作为引用类型传值依然是值传递示例:

package main

import (
	"fmt"
)

func main() {
	slice := []int{1, 2, 3, 4, 5}
	fmt.Printf("切片:%v\n", slice)
	setSliceNil(slice)
	fmt.Printf("切片:%v\n", slice)
}

func setSliceNil(slice []int) {
	slice = nil
	fmt.Printf("切片:%v\n", slice)
}

结果:

切片:[1 2 3 4 5]

切片:[]

切片:[1 2 3 4 5]

经过函数中对slice赋值nil并没有改变main中的slice变量的值,说明go中引用类型的传递也是值传递。

  • 3.再看这个容易让人迷惑的代码示例:

package main

import (
	"fmt"
)

func main() {
	slice := []int{1, 2, 3, 4, 5}
	fmt.Printf("切片:%v\n", slice)
	changeSlice(slice)
	fmt.Printf("切片:%v\n", slice)
}

func changeSlice(slice []int) {
	slice[2] = 10
	fmt.Printf("切片:%v\n", slice)
}

结果:

切片:[1 2 3 4 5]

切片:[1 2 10 4 5]

切片:[1 2 10 4 5]

这里的结果会让人产生困惑,既然是值传递为什么main函数中的切片被修改了呢?

  • 4.标头

搞清楚这个问题,首先要知道什么是“标头”这个概念?引用《Go语言实践》中的一段话:

Go 语言里的引用类型有如下几个:切片、映射、通道、接口和函数类型。当声明上述类型的变量时,创建的变量被称作标头(header)值。从技术细节上说,字符串也是一种引用类型。每个引用类型创建的标头值是包含一个指向底层数据结构的指针。因为标头值是为复制而设计的,所以永远不需要共享一个引用类型的值。标头值里包含一个指针,因此通过复制来传递一个引用类型的值的副本,本质上就是在共享底层数据结构。

总而言之,引用类型在函数传递的时候,是值传递,只不过这里的“值”指的是标头值。

我们分别打印这个切片变量传参前后的指针地址,和传参前后切片中元素的指针地址:

package main

import (
	"fmt"
)

func main() {
	slice := []int{1, 2, 3, 4, 5}
	fmt.Printf("切片:%v 切片变量地址:%p 第一个元素地址:%p\n", slice, &slice, &slice[0])
	changeSlice(slice)
	fmt.Printf("切片:%v 切片变量地址:%p 第一个元素地址:%p\n", slice, &slice, &slice[0])
}

func changeSlice(slice []int) {
	slice[2] = 10
	fmt.Printf("切片:%v 切片变量地址:%p 第一个元素地址:%p\n", slice, &slice, &slice[0])
}

结果:

切片:[1 2 3 4 5] 切片变量地址:0xc00005c400 第一个元素地址:0xc00008a060

切片:[1 2 10 4 5] 切片变量地址:0xc00005c460 第一个元素地址:0xc00008a060

切片:[1 2 10 4 5] 切片变量地址:0xc00005c400 第一个元素地址:0xc00008a060

这再次证明了切片传递的不是指针地址,因为变量前后地址不同。

这也证明了切片的参数传递的是传值的形式,具体是传标头值的拷贝,因为指向元素的指针地址相同。

猜你喜欢

转载自blog.csdn.net/chen_peng7/article/details/89247047
今日推荐