1. package main
    2. import "fmt"
    3. type user struct {
    4. name string
    5. email string
    6. }
    7. //notify使用值接收者实现了一个方法
    8. func (u user)notify() {
    9. fmt.Printf("Sending User Email To %s<%s>\n",u.name,u.email)
    10. }
    11. //changeEmail使用指针接收者实现了一个方法
    12. func (u *user)changeEmail(email string) {
    13. u.email = email
    14. }
    15. func main() {
    16. /*
    17. user类型的值可以用来调用
    18. 使用值接收者声明的方法
    19. */
    20. bill := user{"Bill","bill@email.com"}
    21. bill.notify()
    22. /*
    23. 指向user类型值的指针也可以用来调用
    24. 使用值接收者声明的方法
    25. */
    26. lisa := &user{"Lisa","lisa@email.com"}
    27. lisa.notify()
    28. /*
    29. user类型的值可以用来调用
    30. 使用指针接收者声明的方法
    31. */
    32. bill.changeEmail("bill@newdomain.com")
    33. bill.notify()
    34. /*
    35. 指向user类型值的指针也可以用来调用
    36. 使用值接收者声明的方法
    37. */
    38. lisa.changeEmail("lisa@newdomain.com")
    39. lisa.notify()
    40. }

    当bil(user类型值变量)调用使用值接收者方法时,调用时会使用这个值的一个副本来执行。

    当lisa(一个指向user类型值的指针)调用值接收者方法时,底层会把指针解引用为值:(*lisa).notify()

    当bill(user类型值变量)调用使用指针接收者声明的方法时,首先引用bill值得到一个指针,这样这个指针就能够匹配方法的接收者类型,再进行调用:(&bill).changeEmail ("bill@newdomain.com")

    总结一下,值接收者使用值的副本来调用方法,而指针接收者使用实际值来调用方法

    Go语言既允许使用值,也允许使用指镇上来调用方法,不必严格符合接收者的类型。应该使用值接收者,还是应该使用指针接收者,这个问题有时会比较迷惑人。