值接收者和指针接收者
- 值接收者
使用值接收者声明方法,调用者会用这个值的一个副本来执行 - 指针接收者
使用指针接收者声明方法,这类方法会共享调用方法时接收者所指向的值 - 值接收者和指针接收者比较
type Book struct { id int;name string;price float64 } //使用值接收者 实现方法 func (receiver Book) fun1() { receiver.name = "abc1" } //使用指针接收者 实现方法 func (receiver *Book) fun2() { receiver.name = "abc2" } func main() { book := &Book{id: 1,name: "Think in java",price: 99.99} fmt.Println(book) book.fun1() fmt.Println(book) book.fun2() fmt.Println(book) }
结构类型
结构类型可以分为原始类型和非原始类型
- 原始类型
对该类型做增加或者删除的操作时,该结构类型的值不应该被更改,例如Time
类型
来看一下Time类型的一些方法type Time struct { wall uint64 ext int64 loc *Location }
这个方法使用值接收者,并返回了一个新的Time值。该方法操作的是调用者传入的Time值的副本,并且给调用者返回了一个方法内的Time值的副本func (t Time) Add(d Duration) Time { dsec := int64(d / 1e9) nsec := t.nsec() + int32(d%1e9) if nsec >= 1e9 { dsec++ nsec -= 1e9 } else if nsec < 0 { dsec-- nsec += 1e9 } t.wall = t.wall&^nsecMask | uint64(nsec) // update nsec t.addSec(dsec) if t.wall&hasMonotonic != 0 { te := t.ext + int64(d) if d < 0 && te > t.ext || d > 0 && te < t.ext { // Monotonic clock reading now out of range; degrade to wall-only. t.stripMono() } else { t.ext = te } } return t }
- 非原始类型
对这个类型的值做增加或者删除的操作应该更改值本身,例如File
类型
来看一下File类型的一些方法type File struct { *file // os specific }
该方法即使没有修改接收者的值,依然是用指针接收者来声明的,因为File类型的值具备非原始的本质,所以总是应该被共享,而不是被复制func (f *File) Chdir() error { if err := f.checkValid("chdir"); err != nil { return err } if e := f.pfd.Fchdir(); e != nil { return f.wrapErr("chdir", e) } return nil }
如何选择值接收者和指针接收者
是使用值接受者还是指针接受者,不应该由该方法是否修改了接收到的值来决定,而是由该类型的本质决定
网友评论