go語言介面和方法集問題筆記
阿新 • • 發佈:2019-01-01
注意: 此文章只是我的個人筆記,如有謬誤,錯誤, 請一定指出!
package mainimport "fmt"
//IA test for methodset.
type IA interface {
Value()
Pointer()
}
//A is a test type.
type A int
//Value receiver.
func (a A) Value() {
fmt.Printf("Value:%p, %d\n", &a, a)
}
//Pointer receiver.
func (a *A) Pointer() {
fmt.Printf("Pointer:%p, %d\n", a, *a)
}
func main() {
//type A method set: (a A) Value()
var a A = 1
fmt.Printf("Origin: %p, %d\n", &a, a)
fmt.Println("Value receiver------------------------------")
a.Value()
a.Pointer() //如: (&a).Value(), a value converted to a Pointer by go compiler, so value a can call type *A`s pointer receiver method`
//type *A method set: func (a A) Value(), func (a *A) Pointer()
fmt.Println("Pointer receiver---------------------------")
p := &a
p.Value()
p.Pointer()
fmt.Println("interface call method by type *A-----------------------")
var ia IA
ia = &a
ia.Value()
ia.Pointer()
fmt.Println("interface call method by type A-----------------------")
//對於介面而言, 對於賦值給他的型別,會持有其副本, 即會複製, 且其持有的值不可取地址,會有更嚴格的型別檢查和限制, 不允許做如:A to *A的轉換 ,
//所以當以型別A呼叫func (a *A) Pointer()時是不允許的, 因為型別A的方法集中不包括func (a *A) Pointer(), 也可以說, 型別A的方法集(method set)是型別*A的一個子集。
//總結: 當以非介面型別呼叫pointer receiver method和 value receiver method時 go編譯器會幫助做自動轉換,如: &a 或 *a ; 所以淡化value receiver和pointer receiver方法集的邊界。
//但是介面不允許做這些自動轉換, 一就是一, 嚴格劃清方法集分界,這是golang介面的設計哲學,不是技術問題,
//a interface must check type A or type *A , do not allow convert it between of them, so type A can not call type *A`s Pointer receiver method`
///ia = a //compliation error,coz type not match: A does not implement IA (Pointer method has pointer receiver)
//如果改成: ia = &a 就可以了, 因為:型別*A的方法集包括這個方法, 所以與介面匹配.
//ia.Value()
//ia.Pointer()
}
//program output:
//Origin: 0xc04200e290, 1 //注意: 與此地址不同的情況 , 皆產生了複製, 這就是value receiver與pointer receiver的區別,關注點.
//Value receiver------------------------------
//Value:0xc04200e2a8, 1
//Pointer:0xc04200e290, 1
//Pointer receiver---------------------------
//Value:0xc04200e2f0, 1
//Pointer:0xc04200e290, 1
//interface call method by type *A-----------------------
//Value:0xc04200e308, 1
//Pointer:0xc04200e290, 1
//interface call method by type A-----------------------
注意: 此文章只是我個人筆記, 如有錯漏,請一定指正, 共同學習, 我的郵箱: [email protected]