常见
go语言的参数传递和java一样,只有值传递,没有引用的传递。而且go语言也没有引用类型。变量传递时都是复制一份变量的值来进行传递,比如下面的代码:
func swap(a, b int){
var c int = a
a = b
b = c
}
swap(a, b)
fmt.Println(a,b) // a,b
可以看到变量的值做形参并不能使两变量交换成功,除了用变量的值来做形参,还可以用指针变量来做形参,这时我们使用函数时传的参数就是变量的地址了,这和c是一样的,比如下面:
func swap1(a, b *int){ //这里名字为什么是swap1,因为go我才知道go不支持重载哈哈
var c int = *a
*a = *b
*b = c
}
swap(&a, &b)
fmt.Println(a,b) //b, a
可以看到用指针变量做形参可以使两变量的值交换成功。所以可以知道go语言使用值传递,传变量的值时是将变量的值复制一份做副本,使用指针变量是复制的是变量的地址,所以地址的不变,地址中的变量发生了变换。
结构体变量
这里想将结构体变量拿出来梳理下,因为感觉自己在项目中碰到有时会弄不太清楚,希望能借这里搞清楚。先定义一个结构体。
type AuthData struct {
UserId int64
AppName string
}
authData := new(AuthData)
authData.AppName = "asd"
authData.UserId = 5678
按照上面的顺序我先创建形参为变量的函数,然后改变里面的属性:
//这里形参是结构体变量,我们传的时候需要传*struct作为变量
func function1(data AuthData){
data.UserId = 1234
data.AppName = "asdasd"
}
//使用
function1(*authData)
fmt.Println(authData)
//结果:&{5678 asd} 可以看到结构体属性值并没有改变
可以看到这里传参数时必须使用*authData,说明这里authData这个变量的值是个地址,但我们形参是个变量值,所以我们需要使用*authData传这个结构体的值而不是地址。
接着我们创建形参为指针变量的函数,然后改变里面的属性:
//这里形参是指针变量,使用时我们传的结构体地址
func function2(data *AuthData){
data.UserId = 1234
data.AppName = "asdasd"
}
//使用
function2(authData)
fmt.Println(authData)
//结果:&{1234 asdasd} 可以看到结构体里属性值发生了改变
可以看到传参数时直接传authData,而且从fmt里也可以看出这里这个变量代表的其实是结构体的地址,当我们传地址时,就会改变这个结构体里面的值,跟上面常见的其实是一致的。有时我们会产生疑惑:第一个方法的参数定义的明明是地址变量啊,为什么是结构体的值,emmm,这个我也不太清楚,具体可能是go语法的问题(来位大佬解解惑。。。。),只要记住不带*的变量一定传的就是值,带*变量传的一定是地址并且会改变值就对了。