golang 参数传值
首先 golang 官方表示 golang 的函数调用参数均为值传递,不是指针传递或引用传递。经测试引申出来,当参数变量为指针或隐式指针类型,参数传递方式也是传值(指针本身的 copy)。
“
after they are evaluated, the parameters of the call are passed by value to the
function and the called function begins execution.
”
解释
关于最有争议的 slice 传参是传值还是传引用(或指针)的问题,做一个剖析。
首先,认为 slice 传参是引用传递的大都是根据以下代码情况得出的结果:
package main
import "fmt"
func main(){
slice := make([]int, 3, 5)
fmt.Println("before:", slice)
changeSliceMember(slice)
fmt.Println("after:", slice)
}
func changeSliceMember(slice []int) {
if len(slice) > 1 {
slice[0] = 9
}
}
函数执行结果为:
befor:[0 0 0]
after:[9 0 0]
很显然,slice[0]值在函数内操作过之后确实在 main 中将结果保留了下来。但这不足以表明参数传递方式,参数 slice 无论值还是引用,不影响 slice[0]地址的值。换句话说,只要参数是地址数据,都可以改变其指向的值的内容。
slice
是结构体和指针的混合体,它的每项值,是以指针为内容存储存于 values 中,因此可以改变其值;slice 属性 values、count 和 capacity 等均是值传递。但 values 的值(指针)所指向的堆栈,是存储单元,因此可以保留更改。
因此,以指针和结构体的角度看,都是值传递。
证明 slice 传参过程为值传递的例子
如下代码:
package main
import "fmt"
func main() {
slice := make([]int, 3, 5)
fmt.Println("main-befor send:", slice)
sliceValueAppend(slice)
fmt.Println("main-after send:", slice)
}
func sliceValueAppend(slice []int) {
slice = append(slice, 4)
fmt.Println("fun-after append:", slice)
}
执行结果为:
main-befor send:[0 0 0]
fun-after append:[0 0 0 4]
main-after send:[0 0 0]
因此看出传输方式为值传递。
使用指针变量的例子
使用指针变量作为参数更清晰:
package main
func main() {
value := new(int)
modifyFunc(value)
println("main:", value)
}
func modifyFunc(value *int) {
value = nil
println("modifyFunc:", value)
}
执行结果:
modifyFunc: 0x0
main: 0xc820049f30
可以看出,即使传值为指针,仍未改变变量 value 在 main 中的值。
golang 中的引用
golang 引用的存在
golang 在函数传参过程中均为值传递,但不代表 golang 没有传引用的地方。
golang 闭包访问其外部环境变量时,是通过引用访问的。
闭包举例
package main
import "fmt"
func main() {
value := new(int)
fmt.Println("before:", value)
func () {
value = nil
}()
fmt.Println("after:", value)
}
输出为:
before: 0xc82000a360
after: <nil>
其实闭包的引用传递,相当于全局变量的使用,只是对该值的处理过程进行闭包处理,没什么不好理解的。
总结
- 在 golang 中,基础类型和自定义类型均以
传值
的方式进行参数传递,包括但不限于slice、map、chan
。 - golang 对闭包传值方式是引用传值。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: golang 字符串分割
下一篇: MyBatis 介绍和使用
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论