go方法的深入探究(7.21增补)

前端之家收集整理的这篇文章主要介绍了go方法的深入探究(7.21增补)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
1)哪些类型可以有方法
1)只能对命名类型和命名类型的指针编写方法
2)不能对接口类型和接口类型的指针编写方法
3)只能在定义命名类型的那个包编写其方法

2)receiver是值的方法,编译器会隐式的生成一个receiver是对应类型指针的同名方法。反过来却不会。

3)结构体的匿名字段的类型限制:
1)不可以是未命名类型;
2)可以是命名类型或命令类型的指针类型;
3)接口类型可以,接口类型的指针类型不行;

4)结构体匿名字段的方法向外传递的规则:
1)匿名字段为值类型时:值的方法会传递给结构体的值,指针的方法会传递给结构体的指针;
2)匿名字段为指针类型时:指针的方法会传递给值和指针;
3)匿名字段为接口类型时:方法会传递给值和指针;

5)匿名字段的方法,是被经过包装实现为外围结构体的方法

6)使用具体的类型去调用方法时。
首先,编译器查看该类型下有没有该方法
其次,扩展查看该类型的指针类型或者基类型(如果该类型是指针类型);
最后,如果以上查找都未找到,则会报错。
注:扩展查看不会查看隐式实现的方法(匿名字段传递出来的方法、值=>指针隐式实现的方法

7)具体类型的方法集是以该类型为receiver的方法的集合。

8)接口类型的方法集就是其定义里声明的方法,接口调用方法时类似C++调用函数;接口的指针没有方法集。

9)类型存入接口时只检查方法集;调用接口的方法时也只检查方法集;reflect包同样只查看方法集。

因此:

类型A的方法,A和*A都可以调用
类型A的方法,虽然隐式实现了类型*A的方法,**A却不能调用
类型*A的方法,A、*A、**A都可以调用
不能实现**A的方法
  1. type A ...
  2. func (a A)X(){}
  3. func (a *A)Y(){}
  4. type IX interface{
  5. X()
  6. }
  7. type IY interface{
  8. Y()
  9. }
  10.  
  11. a := A{}
  12. b := &a
  13. c := &b
  14.  
  15. a.X() // ok
  16. b.X() // ok
  17. c.X() // error
  18.  
  19. a.Y() // ok
  20. b.Y() // ok
  21. c.Y() // ok
  22.  
  23. var ix IX
  24. ix = a // ok
  25. ix = b // ok
  26. ix = c // error
  27.  
  28. var iy IY
  29. iy = a // error
  30. iy = b // ok
  31. iy = c // error
  32.  
  33. var jx IX
  34. jx = ix // ok
  35. jx = &ix // error

对于代码

  1. type I interface {
  2. IE()
  3. }
  4.  
  5. type A int
  6.  
  7. func (_ A) VA() {}
  8. func (_ *A) PA() {}
  9.  
  10. type B struct {
  11. I
  12. }
  13. func (_ B) VB() {}
  14. func (_ *B) PB() {}
  15.  
  16. type C struct {
  17. A
  18. }
  19. func (_ C) VC() {}
  20. func (_ *C) PC() {}
  21.  
  22. type D struct {
  23. *A
  24. }
  25. func (_ D) VD() {}
  26. func (_ *D) PD() {}



下面的列表说明了其方法集和方法的来源:

type(类型) explicit(显式定义的方法)
implicit(隐式实现的方法)
inherit(继承自匿名字段的方法)
I IE


*I


A VA


*A PA VA

B VB
IE
*B PB VB IE
C VC
VA
*C PC VC PA,VA
D VD
PA,VA
*D PD VD PA,VA

猜你在找的Go相关文章