修改外部变量值
传递指针给函数不但可以节省内存(因为没有复制变量的值),而且赋予了函数直接修改外部变量的能力,所以被修改的变量不再需要使用
return
返回。如下的例子,reply
是一个指向int
变量的指针,通过这个指针,我们在函数内修改了这个int
变量的数值。
package main
import "fmt"
func main() {
var outside int = 0
changeByPtr(&outside)
fmt.Println(outside)
change := changeByReturn(outside)
fmt.Println(change)
}
//通过指针修改 引用传值
func changeByPtr(o *int) {
*o += 2
}
//通过函数返回值 按值传递
func changeByReturn(o int) int {
return o+2
}
按值传递和引用传递
Go函数中默认使用按值传递来传递参数
也就是传递参数的副本
函数接受参数副本后,在使用变量的过程中可能对副本的值进行修改,但不会影响到原来的变量
如果你希望函数可以直接修改参数的值,而不是对参数的副本进行操作,你需要将参数的地址(变量名前面添加&符号)传递给函数,这就是引用传递,此时传递给函数的是一个指针。如果传递给函数的是一个指针,指针的值(一个地址)会被复制,但指针指的值指向的地址上的值不会被复制;我们可以通过这个指针的值来修改这个值指向的地址的值。
几乎在任何情况下,传递指针的消耗都比传递副本少
在函数调用时,像切片slice,字典map,接口interface,通道channel这样的引用类型都是默认使用引用传递(即使没有显示的指出指针)
探究一下引用传递和按值传递
package main
import "fmt"
type MyStruct struct {
name string
age int
}
func main() {
//test struct
mystruct := new(MyStruct)
mystruct.changeInfo()
fmt.Println(mystruct.name, mystruct.age)
//test slice
myslice := []int32{1, 2, 3, 4}
fmt.Println(myslice)
changeSlice(myslice)
fmt.Println(myslice)
}
func (m *MyStruct) changeInfo() {
//*m.name = "gocloudcoder"
//*m.age = 21
m.name = "gocloudcoder"
m.age = 21
}
func changeSlice(s []int32) {
s[0] = 0
s[1] = 1
s[2] = 2
s[3] = 3
}