Golang介面賦值和方法集
比如《Go語言實戰》中的一個例子:
// compile error// cannot use u (type user) as type notifier in argument to sendNotification:// user does not implement notifier (notify
package main import "fmt" type user struct { namestring email string } type notifier interface { notify() } func (u *user) notify() { fmt.Printf("sending user email to %s<%s>\n", u.name, u.email) } func sendNotification(n notifier) { n.notify() } func main() { u := user{ name:"stormzhu", email: "[email protected]", } sendNotification(u) } // compile error // cannot use u (type user) as type notifier in argument to sendNotification: //user does not implement notifier (notify method has pointer receiver)
如何判斷型別是否實現了某個介面?
- 介面的定義
type iface struct { tab*itab// 型別資訊 data unsafe.Pointer //實際物件指標 } type itab struct { inter *interfacetype // 介面型別 _type *_type// 實際物件型別 fun[1]uintptr// 實際物件方法地址 }
對一個介面賦值的時候,會拷貝型別資訊和該型別的方法集。只要這個型別的方法集中包括這個介面的所有方法,那麼它就是實現了這個介面,才能夠賦值給這個介面。
- 方法集
-
型別
T
的方法集包含所有 receiverT
方法。 -
型別
*T
的方法集包含所有 receiverT
+*T
方法。 -
匿名嵌入
S
,型別T的方法集包含所有 receiverT
+S
方法。 -
匿名嵌入
*S
,型別T的方法集包含所有 receiverT
+S
+*S
方法。 -
匿名嵌入
S
或*S
,型別*T的方法集包含所有 receiverT
+*T
+S
+*S
方法。
總結:
-
T
和*T
不是一個型別,他們的方法集不同 -
型別
*T
的方法集包含所有 receiverT
+*T
方法,型別T
的方法集只包含所有 receiverT
方法。