package main
import "fmt"
type coder interface {
code()
debug()
}
type Gopher struct {
language string
}
//值接收
func (p Gopher) code() {
fmt.Printf("I am coding %s language\n", p.language)
}
//指针接收
func (p *Gopher) debug() {
fmt.Printf("I am debuging %s language\n", p.language)
}
func main() {
var c coder = &Gopher{"Go"} //这种写法没有问题
var c coder = Gopher{"Go"} //这种写法会报错,因为Gopher没有全部实现coder接口。表面上看, *Gopher类型也没有实现code方法,但是因为Gopher类型实现了code方法,所以让*Gopher类型自动拥有了code方法
c.code()
c.debug()
}
两者分别在何时使用:
使用指针作的理由:
- 方法能够修改指向的值。
- 避免在每次调用方法时复制该值,在值的类型为大型结构体时,这样做会更加高效。
是使用值接收还是指针接收,不是由该方法是否修改了调用者(也就是接收者)来决定,而是应该基于该类型的本质。
如果类型具备“原始的本质”,也就是说它的成员都是由 Go 语言里内置的原始类型,如字符串,整型值等,那就定义值接收者类型的方法。像内置的引用类型,如 slice,map,interface,channel,这些类型比较特殊,声明他们的时候,实际上是创建了一个 header, 对于他们也是直接定义值接收者类型的方法。这样,调用函数时,是直接 copy 了这些类型的header,而header本身就是为复制设计的。
如果类型具备非原始的本质,不能被安全地复制,这种类型总是应该被共享,那就定义指针接收者的方法。比如 go 源码里的文件结构体(struct File)就不应该被复制,应该只有一份实体。
有疑问加站长微信联系(非本文作者)