定义
在 Go 语言中,结构体就像是类的一种简化形式,传统面向对象语言中类有属性,同时也有方法。同样 Go 语言中也有方法 method 的概念。它实际上也是函数,只是在声明时,在关键字 func 和函数名之间增加了一个作为接受者(receiver)的参数,通俗的说方法就是带有接收者的函数。
func (r ReceiverType) funcName(parameters) (results)
注意接受者不一定是结构体,可以使用户定义的其他类型。
现在假设有这么一个场景,你定义了一个长方形 Rectangle 结构体,你现在想要计算它的面积,那么按照我们一般的思路应该会用下面的方式来实现。
package mainimport "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 mainimport ("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 等各种类型上面。
