方法
Go 没有类,所以也就不存在真正意义上的方法,Go 中定义的方法是指定了接收者的一种函数
方法只是个带接收者参数的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| type Vertex struct { X, Y float64 }
type MyFloat float64
func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) }
func Abs(v Vertex) float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) }
func main() { v := Vertex{3, 4} fmt.Println(v.Abs()) }
|
方法和函数的区别就是在 func 关键字后面有没有跟接收者参数
而且只能为在同一包内定义的类型的接收者声明方法,而不能为其它包内定义的类型(包括 int 之类的内建类型)的接收者声明方法
所以对于方法的定义我是这么理解的:
在一个包里面,可以自定义结构类型(比如结构体),这些自定义结构所定义的变量就是方法的”目标客户”
这些变量就可以使用那些以他们为”目标客户”的方法,别的自定义结构的变量就不行
方法和指针
众所周知,带指针参数的函数必须接受一个指针
1 2 3 4 5 6
| func Scale(v *Vertex, f float64) { } var v Vertex Scale(v, 5) Scale(&v, 5)
|
但是如果是以指针为接收者的方法的话,接收者既能为值又能为指针
1 2 3 4 5 6 7
| func (v *Vertex) Scale(f float64) { } var v Vertex v.Scale(5) p := &v p.Scale(10)
|
使用指针为接收者的方法是有好处的:方法会直接作用于这个接收者,避免了每次调用方法都要复制一次该值
但是值作为接收者和指针作为接收者不能混用
原因:
接收者是值类型的方法,会自动实现接收者是指针类型的方法
而接收者是指针类型的方法,不会自动实现接收者是值类型的方法
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 29 30 31 32 33 34 35
| package main
import "fmt"
type coder interface { one() two() }
type Vertex struct { S string }
func (v Vertex) one() { fmt.Printf("I am one\n") }
func (v *Vertex) two() { fmt.Printf("I am two\n") }
func main() { var c coder = &Vertex{"Go"} c.one() c.two()
}
|