Go语言到底有没有引用传参(对比 C++ )
C++中三种参数传递方式
值传递:
最常见的一种传参方式,函数的形参是实参的拷贝,函数中改变形参不会影响到函数外部的形参。一般是函数内部修改参数而又不希望影响到调用者的时候会采用值传递。
指针传递
形参是指向实参地址的一个指针,顾名思义,在函数中对形参指向的内容操作,实参本身会被修改。
引用传递
在C++中,引用是变量的别名,实际上是同一个东西,在内存中也存在同一个地址。换句话说,不管在哪里对引用操作,都相当直接操作被引用的变量。
下面看demo:
#include//值传递 voidfunc1(inta){ std::cout<<"值传递,变量地址:"<<&a<<",变量值:"< 输出结果如下:
变量实际地址:0x28feac,变量值:5
值传递,变量地址:0x28fe90,变量值:5
值传递操作后,变量值:5
变量实际地址:0x28feac,变量值:5
指针传递,变量地址:0x28feac,变量值:5
指针传递操作后,变量值:6
变量实际地址:0x28feac,变量值:6
指针传递,变量地址:0x28feac,变量值:6
引用传递操作后,变量值:7
Go中的参数传递
上面介绍了C++的三种参数传递方式,值传递和指针传递容易理解,那么Go是不是也有这些传参方式呢?这引起过争论,但是对比C++的引用传递的概念,我们可以说,Go没有引用传递方式。为什么这么说,因为Go没有变量的引用这一概念。但是Go有引用类型,这个稍后再解释。
先看一个Go传值和传指针的例子:
packagemain import( "fmt" ) funcmain(){ a:=1 fmt.Println("变量实际地址:",&a,"变量值:",a) func1(a) fmt.Println("值传递操作后,变量值:",a) fmt.Println("变量实际地址:",&a,"变量值:",a) func2(&a) fmt.Println("指针传递操作后,变量值:",a) } //值传递 funcfunc1(aint){ a++ fmt.Println("值传递,变量地址:",&a,"变量值:",a) } //指针传递 funcfunc2(a*int){ *a=*a+1 fmt.Println("指针传递,变量地址:",a,"变量值:",*a) }输出结果如下:
变量实际地址:0xc04203c1d0变量值:1
值传递,变量地址:0xc04203c210变量值:2
值传递操作后,变量值:1
变量实际地址:0xc04203c1d0变量值:1
指针传递,变量地址:0xc04203c1d0变量值:2
指针传递操作后,变量值:2
可以看出,Go基本类型的值传递和指针传递和C++并没有什么不同,但是它没有变量的引用这一概念。那Go的引用类型怎么理解呢?Go的引用类型
在Go中,引用类型包含切片、字典、通道等。以切片为例,传切片是传引用么?
举个例子:
packagemain import( "fmt" ) funcmain(){ m1:=make([]string,1) m1[0]="test" fmt.Println("调用func1前m1值:",m1) func1(m1) fmt.Println("调用func1后m1值:",m1) } funcfunc1(a[]string){ a[0]="val1" fmt.Println("func1中:",a) }输出结果如下:
调用func1前m1值:[test]
func1中:[val1]
调用func1后m1值:[val1]
函数中对切片做出的修改影响了实际参数的值。是不是说这事引用传递?
其实并不是,要回答这个问题,首先得搞清楚调用函数切片m1到底有没有改变。首先我们要认清楚切片的本质。
一个切片是一个数组片段的描述。它包含了指向数组的指针,片段的长度。
也就是说,上面我们打印的并不是切片本身,而是切片指向的数组。再举个例子,验证一下切片到底有没有发生变化。
packagemain import( "fmt" ) funcmain(){ m1:=make([]string,1) m1[0]="test" fmt.Println("调用func1前m1值:",m1,cap(m1)) func1(m1) fmt.Println("调用func1后m1值:",m1,cap(m1)) } funcfunc1(a[]string){ a=append(a,"val1") fmt.Println("func1中:",a,cap(a)) }输出结果如下:
调用func1前m1值:[test]1
func1中:[testval1]2
调用func1后m1值:[test]1
这个结果说明,调用前后切片并没有发生变化。之前例子中所谓的“变化”其实是切片中指向数组的指针指向的数组的元素发生了变化,这句话可能比较拗口,但实际如此。再次证明,引用类型的传参不是pass-by-reference。
想透彻的了解一个切片是一个数组片段的描述。它包含了指向数组的指针,片段的长度这句话,有兴趣可以看这篇文章:https://www.nhooo.com/kf/201604/499045.html。学习一下切片的内存模型。
总结
总结很简单,语言也需要透过现象看本质。还有本文的结论需要记住:
Thereisnopass-by-referenceinGo.
以上所述是小编给大家介绍的Go语言到底有没有引用传参(对比C++),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。