499689317 / notes

note
2 stars 0 forks source link

Go语言特性 #22

Open 499689317 opened 4 years ago

499689317 commented 4 years ago

Go Struct方法定义中指针接收与值接收

如果实现了接收者是值类型的方法,会隐含地也实现了接收者是指针类型的方法。

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) }

1. 方式一

// 正常打印 func main() { var c coder = &Gopher{"Go"} c.code() c.debug() }

2. 方式二

// 报错 func main() { var c coder = Gopher{"Go"} c.code() c.debug() }


* 两者分别使用场景
____
如果方法的接收者是值类型,无论调用者是对象还是对象指针,修改的都是对象的副本,不影响调用者;如果方法的接收者是指针类型,则调用者修改的是指针指向的对象本身。

使用指针作为方法的接收者的理由:

方法能够修改接收者指向的值。
避免在每次调用方法时复制该值,在值的类型为大型结构体时,这样做会更加高效。
是使用值接收者还是指针接收者,不是由该方法是否修改了调用者(也就是接收者)来决定,而是应该基于该类型的本质。

如果类型具备“原始的本质”,也就是说它的成员都是由 Go 语言里内置的原始类型,如字符串,整型值等,那就定义值接收者类型的方法。像内置的引用类型,如 slice,map,interface,channel,这些类型比较特殊,声明他们的时候,实际上是创建了一个 header, 对于他们也是直接定义值接收者类型的方法。这样,调用函数时,是直接 copy 了这些类型的 header,而 header 本身就是为复制设计的。

如果类型具备非原始的本质,不能被安全地复制,这种类型总是应该被共享,那就定义指针接收者的方法。比如 go 源码里的文件结构体(struct File)就不应该被复制,应该只有一份实体
____

### 接口interface
* 因为空接口没有定义任何函数,所以Go中任何类型都实现了空接口