golang中介面賦值與方法集

2021-09-13 02:57:17 字數 2211 閱讀 6895

golang中的介面可以輕鬆實現c++中的多型,而且沒有繼承自同一父類的限制,感覺方便很多。但是在使用的時候,如果沒有理解,也可能會遇到"坑"。比如《go語言實戰》中的乙個例子:

package main

import "fmt"

type user struct

type notifier inte***ce

func (u *user) notify()

func sendnotification(n notifier)

func main()

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)

報的錯是u沒有實現notifier這個介面,實現了這個介面的是*user型別,而不是user型別,uuser型別,所以不能賦值給notifier這個介面。

既然如此,修改為sendnotification(&u)就ok了。然而問題是,如何理解到底是t型別還是*t型別實現了某個介面呢?

參考雨痕的《go語言學習筆記》第七章,go語言中的介面定義如下:

type iface struct 

type itab struct

雖然具體的細節操作不太懂,但是可以知道,對乙個介面賦值的時候,會拷貝型別資訊和該型別的方法集。這就類似於c++多型中的虛指標(vptr)和虛函式表(vtable)了。我理解的是,只要這個型別的方法集中包括這個介面的所有方法,那麼它就是實現了這個介面,才能夠賦值給這個介面,那麼問題來了,乙個型別的方法集是什麼呢?

雖然看起來比較複雜,但總結完就一話,*t型別就是厲害,方法集包括t*t的方法。

所以文章開頭的例子中,uuser型別,方法集是空的,不算是實現了notifier介面。

當在糾結應該將t型別還是*t型別賦值給某個介面的時候,第一步就是看方法集,看一看該型別到底有沒有實現這個介面。(所以t*t不是乙個型別。。。)

go語言的內建庫中有定義了很多介面,如error介面,

type error inte***ce
內建的errors包實現了這個介面:

// package errors implements functions to manipulate errors.

package errors

// new returns an error that formats as the given text.

func new(text string) error

}// errorstring is a trivial implementation of error.

type errorstring struct

func (e *errorstring) error() string

可以看到new方法返回值是error介面,而只有*errorstring型別實現了這個介面,所以new方法返回的是&errorstring而不是errorstring

golang 方法與介面

在程式語言中,方法與函式的概念來搞清楚。函式指的是乙個封裝的 塊,我們可以直接呼叫它,並且返回結果。而方法其實也是一種函式,只不過方法需要和某個物件繫結。golang並沒有類的概念,不過仍然有方法和介面這些概念。方法接收者是乙個特殊引數,給函式指定了這個引數之後,函式就成為方法了。這個特性有點像ko...

使用方法集與介面

作用於變數上的方法實際上是不區分變數到底是指標還是值的。當碰到介面型別值時,這會變得有點複雜,原因是介面變數中儲存的具體值是不可定址的,幸運的是,如果使用不當編譯器會給出錯誤。考慮下面的程式 package main import fmt type list int func l list len ...

golang結構體與方法

type people inte ce type student struct func stu student speak think string talk string else return func main think speak fmt.println peo.speak think ...