golang传参方式 | KaiQ.Gu|KerwinKoo Blog
golang 参数传值
首先,golang官方表示golang的函数调用参数均为值传递,不是指针传递或引用传递。经测试引申出来,当参数变量为指针或隐式指针类型,参数传递方式也是传值(指针本身的copy)。
after they are evaluated, the parameters of the call are passed by value to thefunction and the called function begins execution.解释
关于最有争议的slice传参是传值还是传引用(或指针)的问题,做一个剖析。
首先,认为slice传参是引用传递的大都是根据以下代码情况得出的结果:
1 | package main |
函数执行结果为:
1 | befor:[0 0 0] |
很显然,slice[0]值在函数内操作过之后确实在main中将结果保留了下来。但这不足以表明参数传递方式,参数slice无论值还是引用,不影响slice[0]地址的值。换句话说,只要参数是地址数据,都可以改变其指向的值的内容。
slice是结构体和指针的混合体,它的每项值,是以指针为内容存储存于values中,因此可以改变其值;slice属性values、count 和 capacity等均是值传递。但values的值(指针)所指向的堆栈,是存储单元,因此可以保留更改。
因此,以指针和结构体的角度看,都是值传递。
证明slice传参过程为值传递的例子
如下代码:
1 | package main |
执行结果为:
1 | main-befor send:[0 0 0] |
因此看出传输方式为值传递。
使用指针变量的例子
使用指针变量作为参数更清晰:
1 | package main |
执行结果:
1 | modifyFunc: 0x0 |
可以看出,即使传值为指针,仍未改变变量value在main中的值。
golang中的引用
golang引用的存在
golang在函数传参过程中均为值传递,但不代表golang没有传引用的地方。
golang闭包访问其外部环境变量时,是通过引用访问的。
闭包举例
1 | package main |
输出为:
1 | before: 0xc82000a360 |
其实闭包的引用传递,相当于全局变量的使用,只是对该值的处理过程进行闭包处理,没什么不好理解的。
总结
- 在golang中,基础类型和自定义类型均以
传值的方式进行参数传递,包括但不限于slice、map、chan。 - golang对闭包传值方式是引用传值。