golang 参数传值

发布于 2024-08-17 09:39:20 字数 2699 浏览 23 评论 0

首先 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

小猫一只

暂无简介

文章
评论
28 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文