我们知道,在Go语言中, 函数 和 方法 的很大区别就是有没有接收器!
今天,咱们明确的是方法里中的方法值与方法表达式。
一、方法值
在 函数变量 这一节中,你一定对“函数值”有所了解了。 对于方法值,大家可以看下面的代码:
p := Point{1, 2}
q := Point{4, 6}
distanceFromP := p.Distance // method value
fmt.Println(distanceFromP(q)) // "5"
var origin Point // {0, 0}
fmt.Println(distanceFromP(origin)) // "2.23606797749979", sqrt(5)
scaleP := p.ScaleBy // method value
scaleP(2) // p becomes (2, 4)
scaleP(3) // then (6, 12)
scaleP(10) // then (60, 120)
p.Distance叫作“选择器”,选择器会返回一个方法“值”:一个将方法(Point.Distance)绑定到特定接收器变量的函数。这个函数可以不通过指定其接收器,只要传入函数的参数即可被调用!
二、方法表达式
当T是一个类型时,方法表达式可能会写作T.f或者(*T).f,会返回一个函数“值”,这种函数会将其第一个参数用作接收器,所以可以用通常(不写选择器)的方式来对其进行调用:
p := Point{1, 2}
q := Point{4, 6}
distance := Point.Distance // method expression
fmt.Println(distance(p, q)) // "5"
fmt.Printf("%T\n", distance) // "func(Point, Point) float64"
通过Point.Distance得到的函数需要比实际的Distance方法多一个参数,即其需要用第一个额外参数指定接收器,后面排列Distance方法的参数。
当你根据一个变量来决定调用同一个类型的哪个函数时,方法表达式就显得很有用了。你可以根据选择来调用接收器各不相同的方法。下面就是个简单的例子:
type Point struct{ X, Y float64 }
func (p Point) Add(q Point) Point { return Point{p.X + q.X, p.Y + q.Y} }
func (p Point) Sub(q Point) Point { return Point{p.X - q.X, p.Y - q.Y} }
type Path []Point
func (path Path) TranslateBy(offset Point, add bool) {
var op func(p, q Point) Point
if add {
op = Point.Add
} else {
op = Point.Sub
}
for i := range path {
// Call either path[i].Add(offset) or path[i].Sub(offset).
path[i] = op(path[i], offset)
}
}
这一小节的内容很简单,你都学会了吗?