1. 方法集

    Golang方法集 :每个类型都有与之关联的方法集,这会影响到接口实现规则。

    用实例 value 和 pointer 调用方法 (含匿名字段) 不受方法集约束,编译器总是查找全部方法,并自动转换 receiver 实参。

    Go 语言中内部类型方法集提升的规则:

    类型 T 方法集包含全部 receiver T 方法。

    1. import (
    2. "fmt"
    3. )
    4. type T struct {
    5. int
    6. }
    7. func (t T) test() {
    8. fmt.Println("类型 T 方法集包含全部 receiver T 方法。")
    9. }
    10. func main() {
    11. t1 := T{1}
    12. fmt.Printf("t1 is : %v\n", t1)
    13. t1.test()
    14. }
    1. t1 is : {1}
    2. 类型 T 方法集包含全部 receiver T 方法。

    类型 *T 方法集包含全部 receiver T + *T 方法。

    输出结果:

    1. t2 is : &{1}
    2. 类型 *T 方法集包含全部 receiver T 方法。
    3. 类型 *T 方法集包含全部 receiver *T 方法。

    给定一个结构体类型 S 和一个命名为 T 的类型,方法提升像下面规定的这样被包含在结构体方法集中:

    如类型 S 包含匿名字段 T,则 S 和 *S 方法集包含 T 方法。

    1. package main
    2. import (
    3. "fmt"
    4. type S struct {
    5. T
    6. }
    7. type T struct {
    8. int
    9. }
    10. func (t T) testT() {
    11. fmt.Println("如类型 S 包含匿名字段 T,则 S 和 *S 方法集包含 T 方法。")
    12. }
    13. func main() {
    14. s1 := S{T{1}}
    15. s2 := &s1
    16. fmt.Printf("s1 is : %v\n", s1)
    17. s1.testT()
    18. fmt.Printf("s2 is : %v\n", s2)
    19. s2.testT()
    20. }

    输出结果:

    如类型 S 包含匿名字段 *T,则 S 和 *S 方法集包含 T + *T 方法。

    这条规则说的是当我们嵌入一个类型的指针,嵌入类型的接受者为值类型或指针类型的方法将被提升,可以被外部类型的值或者指针调用。

    1. package main
    2. import (
    3. "fmt"
    4. )
    5. }
    6. type T struct {
    7. int
    8. }
    9. func (t T) testT() {
    10. fmt.Println("如类型 S 包含匿名字段 *T,则 S 和 *S 方法集包含 T 方法")
    11. }
    12. func (t *T) testP() {
    13. fmt.Println("如类型 S 包含匿名字段 *T,则 S 和 *S 方法集包含 *T 方法")
    14. }
    15. func main() {
    16. s1 := S{T{1}}
    17. s2 := &s1
    18. fmt.Printf("s1 is : %v\n", s1)
    19. s1.testT()
    20. s1.testP()
    21. fmt.Printf("s2 is : %v\n", s2)
    22. s2.testT()
    23. s2.testP()
    24. }

    输出结果:

    1. s1 is : {{1}}
    2. 如类型 S 包含匿名字段 *T,则 S *S 方法集包含 T 方法
    3. 如类型 S 包含匿名字段 *T,则 S *S 方法集包含 *T 方法
    4. s2 is : &{{1}}
    5. 如类型 S 包含匿名字段 *T,则 S *S 方法集包含 T 方法