声明
在函数声明时, 在其名字前放上一个类型为 T 的变量, 即是一个方法. 此处的变量叫做方法的接收器(receiver). 这个方法会将函数附加到 T 类型上. 这就相当于为 T 类型添加一个独占的方法.
你可以为同一包内定义的结构体类型(或其它使用 type
关键字定义的类型)定义方法.
方法隶属的类型其实并不局限于结构体类型, 但必须是某个自定义的数据类型, 并且不能是任何接口类型.
将属性及其能力(或者说数据及其操作)封装在一起, 是面向对象编程的一个主要原则.
方法就是一类带特殊的接收者参数的函数.
type Vertex struct {
X, Y float64
}
// Abs 方法是绑定在 Vertex 结构体上的函数
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
func main() {
v := Vertex{3, 4}
fmt.Println(v.Abs())
}
基于指针的方法
如果一个方法的接收者是 T 类型的, 那么该方法就是基本类型 T 的一个指针方法.
你可以为类型的指针(指针接收者)声明方法. 这意味着对于某类型 T, 接收者的类型可以用 T 的文法.
在声明方法时, 如果一个类型名本身是一个指针的话, 是不允许其出现在接收器中的.
指针接收者的方法被调用时, 接收者既能为值又能为指针. 即不管你的 method 和 receiver 是指针还是非指针, 都可以通过指针/非指针类型进行调用, 编译器会帮你做类型转换.
我们不能通过一个无法取到地址的接收器来调用指针方法, 比如临时变量.
如果类型 T 的所有方法都是用 T 类型自己来做接收器(而不是 *T
), 那么拷贝这种类型就是安全的, 调用他的任何一个方法产生的也是一个拷贝的值.
使用指针接收者的原因有二:
- 方法能够修改其接收者指向的值.
- 这样可以避免在每次调用方法时复制该值. 若值的类型为大型结构体时, 这样做会更加高效.
Nil 也是一个合法的接收器类型.
当 T 是一个类型时, 方法表达式可能会写作 T.f
或 (*T).f
, 这个表达式会返回一个函数值.