说明: 理解本文的前提是你对Go语言已有一定的基础了解。
什么是指针: 即一个指针变量指向一个值的内存地址。
使用值类型和指针类型的区别 首先,我们来看一个计算面积的代码,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package mainimport ( "fmt" ) type Rect struct { width float64 length float64 } func (rect Rect) area() float64 { return rect.width * rect.length } func (rect *Rect) area1() float64 { rect.width *= 2 rect.length *= 2 return rect.width * rect.length } func main () { var rect = new (Rect) rect.width = 100 rect.length = 200 fmt.Println("Width:" , rect.width, "Length:" , rect.length,"Area:" , rect.area()) fmt.Println("Width:" , rect.width, "Length:" , rect.length,"Area:" , rect.area1()) }
在Go语言中,默认是按值传递。当一个变量当作参数传递的时候,会创建一个变量的副本,然后传递给函数或者方法,你可以看到这个副本的地址和变量的地址是不一样的。当变量当做指针被传递的时候,一个新的指针被创建,它指向变量同样的内存地址,所以你可以将这个指针看成原始变量指针的副本。
故此 1.是否使用结构体指针,取决于是否要在函数内部改变传递进来的参数的值。如果你的struct足够大,使用指针可以加快效率。如果不使用指针,在函数内部则无法修改struct中的值。 2.结构体赋值默认是按值传递,你要改变原来的那个值,要使用指针(即如果你要修改对象本身,那就要传指针,否则修改的是副本)。
再来比较下使用指针修改原始变量的值。代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport ( "fmt" ) func main () { i := 1 var p *int p=&i fmt.Printf("i=%d;p=%d;*p=%d\n" ,i,p,*p) *p=2 fmt.Printf("i=%d;p=%d;*p=%d\n" ,i,p,*p) i := 3 fmt.Printf("i=%d;p=%d;*p=%d\n" ,i,p,*p) }
以上输出结果为:
1 2 3 i=1;p=824633802904;*p=1 i=2;p=824633802904;*p=2 i=3;p=824633802904;*p=3
向函数传递指针参数 Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可。以下实例演示了如何向函数传递指针,并在函数调用后修改函数内的值,:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package mainimport "fmt" func main () { var a int = 100 var b int = 200 fmt.Printf("交换前 a 的值 : %d\n" , a ) fmt.Printf("交换前 b 的值 : %d\n" , b ) swap(&a, &b); fmt.Printf("交换后 a 的值 : %d\n" , a ) fmt.Printf("交换后 b 的值 : %d\n" , b ) } func swap (x *int , y *int ) { var temp int temp = *x *x = *y *y = temp }
输出结果为:
1 2 3 4 交换前 a 的值 : 100 交换前 b 的值 : 200 交换后 a 的值 : 200 交换后 b 的值 : 100
go什么情况下使用指针
推荐在方法上使用指针(前提是这个类型不是 map、slice 等引用类型)
当结构体较大的时候使用指针会更高效,可以避免内存拷贝,“结构较大” 到底多大才算大可能需要自己或团队衡量,如超过 5 个字段或者根据结构体内存占用来计算
如果要修改结构体内部的数据或状态必须使用指针
如果方法的receiver是map、slice 、channel等引用类型不要使用指针
小数据类型如 bool、int 等没必要使用指针传递
如果该函数会修改receiver或变量等,使用指针