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的方法;
type A ...
func (a A)X(){}
func (a *A)Y(){}
type IX interface{
	X()
}
type IY interface{
	Y()
}

a := A{}
b := &a
c := &b

a.X() // ok
b.X() // ok
c.X() // error

a.Y() // ok
b.Y() // ok
c.Y() // ok

var ix IX
ix = a // ok
ix = b // ok
ix = c // error

var iy IY
iy = a // error
iy = b // ok
iy = c // error

var jx IX
jx = ix  // ok
jx = &ix // error

對於代碼: 函數

type I interface {
	IE()
}

type A int

func (_ A) VA() {}
func (_ *A) PA() {}

type B struct {
	I
}
func (_ B) VB() {}
func (_ *B) PB() {}

type C struct {
	A
}
func (_ C) VC() {}
func (_ *C) PC() {}

type D struct {
	*A
}
func (_ D) VD() {}
func (_ *D) PD() {}



下面的列表說明了其方法集和方法的來源: spa

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
相關文章
相關標籤/搜索