方法主要来源于OOP语言,在传统面向对象语言中,我们会用一个“类”来封装属于自己的数据和函数,这些类的函数就叫做方法
虽然Go不是经典意义上的面向对象语言,但是我们可以在一些接收者(自定义类型,结构体)上定义函数,同理这些接受者的函数在Go里面也叫做方法
方法的声明
Q:什么是接收者?
必须指定接收者
func (t T) F(){}
注意:
- 接受者的类型只能为用关键字type定义的类型,例如自定义类型,结构体
- 同一个接收者的方法名不能重复(没有重载),如果是结构体,方法名还不能和字段名重复
- 值作为接收者无法修改其值,如果有更改需求,需要使用指针类型。
指针接收器与值类型
前面都是带有值接收器的方法
可以使用指针接收器创建方法
值和指针接收器的方法在于,在具有指针接收器的方法内部所做的更改对调用者是可见的,而在值接收器中则不然。
何时使用指针接收和值接收
通常,当调用者应该可以看到方法内对接收器所做的更改时,可以使用指针接收器
指针接收器也可用于复制数据结构成本高昂的地方。考虑一个具有许多字段的结构。将此结构用作方法中的值接收器将需要复制方法中的整个结构,这将是昂贵的。在这种情况下,如果使用指针接收器,则不会复制结构,而在方法中只会使用指向它的指针。
在所有其他情况下,可以使用值接收器。
命名冲突
a.接收者定义的方法名不能重复
package main
type T struct{}
func (T) F() {}
func (T) F(a string) {}//这是不被允许的哦
func main() {
t := T{}
t.F()
}
b.结构体方法名不能和字段重复
package main
type T struct{
F string
}
func (T) F(){}//方法名和结构体字段名重复了
func main() {
t := T{}
t.F()
}
接受者可以同时为值和指针
package main
type T struct{}
func (T) F() {}
func (*T) N() {}
func main() {
t := T{}
t.F()
t.N()
t1 := &T{} // 指针类型
t1.F()
t1.N()
}
无论值类型T还是指针类型&T都可以同时访问F和N
值和指针作为接收者的区别
package main
import "fmt"
type T struct {
value int
}
func (m T) StayTheSame() {
m.value = 3
}
func (m *T) Update() {
m.value = 3
}
func main() {
m := T{0}
fmt.Println(m) // {0}
m.StayTheSame()
fmt.Println(m) // {0}
m.Update()
fmt.Println(m) // {3}
}
值作为接收者(T)不会修改结构体值,而指针*T可以修改