定义
在 Go 语言中,结构体就像是类的一种简化形式,传统面向对象语言中类有属性,同时也有方法。同样 Go 语言中也有方法 method
的概念。它实际上也是函数,只是在声明时,在关键字 func
和函数名之间增加了一个作为接受者(receiver)的参数,通俗的说方法就是带有接收者的函数。
func (r ReceiverType) funcName(parameters) (results)
注意接受者不一定是结构体,可以使用户定义的其他类型。
现在假设有这么一个场景,你定义了一个长方形 Rectangle
结构体,你现在想要计算它的面积,那么按照我们一般的思路应该会用下面的方式来实现。
package main
import "fmt"
type Rectangle struct {
width, height float64
}
func area(r Rectangle) float64 {
return r.width * r.height
}
func main() {
r1 := Rectangle{12, 2}
r2 := Rectangle{9, 4}
fmt.Println("Area of r1 is: ", area(r1))
fmt.Println("Area of r2 is: ", area(r2))
}
这段代码可以计算出来长方形的面积,但是 area()
不是作为 Rectangle
的方法实现的(类似面向对象里面的方法),而是将 Rectangle
的对象(如 r1
, r2
)作为参数传入函数计算面积的。
这样实现当然没有问题,但是当需要增加圆形、正方形、五边形甚至其它多边形的时候,你想计算他们的面积的时候怎么办啊?那就只能增加新的函数!但是函数名你就必须要跟着换了,变成 area_rectangle
, area_circle
, area_triangle
…
很显然,这样的实现并不优雅,并且从概念上来说“面积”是“形状”的一个属性,它是属于这个特定的形状的,就像长方形的长和宽一样。这是 method
就排上了用场。下面我们将开始的例子用 method
来实现:
package main
import (
"fmt"
"math"
)
type Rectangle struct {
width, height float64
}
type Circle struct {
radius float64
}
func (r Rectangle) area() float64 {
return r.width * r.height
}
func (c Circle) area() float64 {
return c.radius * c.radius * math.Pi
}
func main() {
r1 := Rectangle{12, 2}
r2 := Rectangle{9, 4}
c1 := Circle{10}
c2 := Circle{25}
fmt.Println("Area of r1 is: ", r1.area())
fmt.Println("Area of r2 is: ", r2.area())
fmt.Println("Area of c1 is: ", c1.area())
fmt.Println("Area of c2 is: ", c2.area())
}
在使用 method
的时候重要注意几点:
- 虽然
method
的名字一模一样,但是如果接收者不一样,那么method
就不一样; method
里面可以访问接收者的字段;- 调用
method
通过.
访问,就像struct
里面访问字段一样。
同时再次强调 method
并不是只能作用在 struct
上面,它可以定义在任何你自定义的类型、内置类型、 struct
等各种类型上面。