Go 使用方法和指针,与结构体一样,明白如何使用方法和指针也很重要。您已经看到,方法是一个接受被称为接收者的特殊参数的函数,接收者可以是指针,也可以是值,但两者的差别非常微妙。假设有一个存储三角形数据的结构体。
type Triangle struct {
width float64
height float64
}
为计算三角形的面积,一个简单的公式是将高度和底相乘,再乘以1/2
。虽然这可以直接使用结构体的数据字段来计算,但更简结的方式是定义一个方法。方法area返回前述公式的结果。请注意,接收者是指向结构体Triangle的指针,这是由星号指定的。
func (t *Triangle) area() float64 {
return 0.5 * (t.width * t.height)
}
下面程序演示了如何向方法传递指针引用。
package main
import (
"fmt"
)
type Triangle struct {
base float64
height float64
}
func (t *Triangle) area() float64 {
return 0.5 * (t.base * t.height)
}
func main() {
t := Triangle{base: 3, height: 1}
fmt.Println(t.area())
}
执行结果:
为理解将接收者参数声明为指针引用和值引用的差别,我们来看一个简单的示例,它修改结构体中定义的三角形的底值。假设要修改三角形的底值,可使用方法changeBase来实现。
func (t Triangle) changeBase(f float64) {
t.base = f
return
}
在这个示例中,注意到指定接收者参数类型时没有在Triangle前面加上星号,这意味着接收者参数是值而不是指针。如下程序是一个完整的示例,它在结构体Triangle的方法集中添加了方法changeBase。
package main
import (
"fmt"
)
type Triangle struct {
base float64
height float64
}
func (t Triangle) changeBase(f float64) {
t.base = f
return
}
func main() {
t := Triangle{base: 3, height: 1}
t.changeBase(4)
fmt.Println(t.base)
}
执行结果:
之所以打印的是3,是因为方法changeBase接受的是一个值引用。这意味着这个方法操作的是结构体Triangle的副本,而原始结构体不受影响。在方法changeBase中,修改的是原始Triangle结构体的副本的t.base。
将指针作为接收者的方法能够修改原始结构体的数据字段,这是因为它使用的是指向原始结构体内存单元的指针,因此操作的不是原始结构体的副本。
可修改程序清单,将接收者参数的类型声明为指针。这样调用方法时,将修改原始结构体的数据字段。
package main
import (
"fmt"
)
type Triangle struct {
base float64
height float64
}
func (t *Triangle) changeBase(f float64) {
t.base = f
return
}
func main() {
t := Triangle{base: 3, height: 1}
t.changeBase(4)
fmt.Println(t.base)
}
执行结果:
指针和值之间的差别很微妙,但选择使用指针还是值这一点很简单:如果需要修改原始结构体,就使用指针;如果需要操作结构体,但不想修改原始结构体,就使用值。
酷客教程相关文章:
评论前必须登录!
注册