声明

在函数声明时, 在其名字前放上一个类型为 T 的变量, 即是一个方法. 此处的变量叫做方法的接收器(receiver). 这个方法会将函数附加到 T 类型上. 这就相当于为 T 类型添加一个独占的方法.
你可以为同一包内定义的结构体类型(或其它使用 type 关键字定义的类型)定义方法.
方法隶属的类型其实并不局限于结构体类型, 但必须是某个自定义的数据类型, 并且不能是任何接口类型.
将属性及其能力(或者说数据及其操作)封装在一起, 是面向对象编程的一个主要原则.

方法就是一类带特殊的接收者参数的函数.

  1. type Vertex struct {
  2. X, Y float64
  3. }
  4. // Abs 方法是绑定在 Vertex 结构体上的函数
  5. func (v Vertex) Abs() float64 {
  6. return math.Sqrt(v.X * v.X + v.Y * v.Y)
  7. }
  8. func main() {
  9. v := Vertex{3, 4}
  10. fmt.Println(v.Abs())
  11. }

基于指针的方法

如果一个方法的接收者是 T 类型的, 那么该方法就是基本类型 T 的一个指针方法.
你可以为类型的指针(指针接收者)声明方法. 这意味着对于某类型 T, 接收者的类型可以用
T 的文法.
在声明方法时, 如果一个类型名本身是一个指针的话, 是不允许其出现在接收器中的.
指针接收者的方法被调用时, 接收者既能为值又能为指针. 即不管你的 method 和 receiver 是指针还是非指针, 都可以通过指针/非指针类型进行调用, 编译器会帮你做类型转换.
我们不能通过一个无法取到地址的接收器来调用指针方法, 比如临时变量.
如果类型 T 的所有方法都是用 T 类型自己来做接收器(而不是 *T), 那么拷贝这种类型就是安全的, 调用他的任何一个方法产生的也是一个拷贝的值.
使用指针接收者的原因有二:

  1. 方法能够修改其接收者指向的值.
  2. 这样可以避免在每次调用方法时复制该值. 若值的类型为大型结构体时, 这样做会更加高效.

Nil 也是一个合法的接收器类型.

当 T 是一个类型时, 方法表达式可能会写作 T.f(*T).f, 这个表达式会返回一个函数值.