方法
方法声明
- 方法的声明和普通函数的声明类似,只是在函数名字前面多了一个参数。这个参数把这个方法绑定到这个参数对应的类型上。
接收者
-
值接收者
-
指针接收者
-
go语言即允许使用值,也允许使用指针来调用方法,Go会做隐式转换。值接收者使用值的副本来调用方法,而指针接受者使用实际值来调用方法。
-
nil是一个合法的接收者。就像允许一些函数允许nil指针作为实参,方法的接收者也一样,尤其是当nil是类型中有意义的零值(如map、slice),更是如此。
通过结构体内嵌组成类型
- 子类接收者(包括值和指针)可以调用父类声明的方法,原因是编译器会自动为子类生成接收者类型是子类的方法
方法变量和方法表达式
m1 := p.scaleV2 //方法变量
m1(1.2)
m2 := Point.scale //方法表达式
m2(point,1.0)
封装
-
Go语言中封装的单元是包而不是类型,无论是函数内的代码还是方法内的代码,结构体类型内的字段对于同一个包中所有的代码都是可见的。
-
getter和setter函数。命名getter方法的时候通常将Get前缀省略。
package main
import (
"fmt"
"sync"
)
type Point struct {
x, y float32
}
type ColorPoint struct {
clolor int
Point
}
func (p *Point) scale(factor float32) {
p.x *= factor
p.y *= factor
}
func (p Point) scaleV2(factor float32) {
fmt.Println("scaleV2")
}
type circle *float32
//不允许对指针类型定义方法
//Invalid receiver type 'circle' ('circle' is a pointer type)
//func (c *circle) circlePi() {
//
//}
//匿名结构体 cheche继承了Mutex的方法
var cache = struct {
c map[string]string
sync.Mutex
}{c: make(map[string]string)}
func main() {
cache.Lock()
fmt.Println(cache.c[""])
point := Point{x: 100, y: 50}
(&point).scale(1.2) //120.00001 60.000004
//如果接收者是指针,使用变量调用方法,会对变量做隐式转换&p
point.scale(1.2) //144.00002 72.00001
fmt.Println(point.x, point.y)
//如果接收者是类型 使用指针去调用方法也是可以的 会隐式转换*P
p := &point
p.scaleV2(100.0)
colorPoint := ColorPoint{100, Point{x: 1, y: 2}}
colorPoint.scale(100)
colorPoint.scaleV2(2)
cache.Unlock()
m1 := p.scaleV2 //方法变量
m1(1.2)
m2 := Point.scale //方法表达式
m2(point,1.0)
}