3 回答

TA貢獻1886條經驗 獲得超2個贊
您可以參考文章“ 如何在Go中使用接口 ”(基于“ Russ Cox的接口描述 ”):
什么是界面?
界面是兩件事:
這是一套方法,
但它也是一種類型
該
interface{}
類型的空接口是沒有方法的接口。由于沒有implements關鍵字,所有類型都實現至少零方法,并且自動完成滿足接口,所有類型都滿足空接口。
這意味著如果您編寫一個將interface{}
值作為參數的函數,則可以為該函數提供任何值。
(這就是Msg
你的問題所代表的:任何價值)
func DoSomething(v interface{}) { // ...}
這是令人困惑的地方:
在
DoSomething
函數內部,什么是v
類型?初學者被認為是“
v
任何類型”,但這是錯誤的。v
不屬于任何類型; 它是interface{}
類型的。將值傳遞給
DoSomething
函數時,Go運行時將執行類型轉換(如果需要),并將值轉換為interface{}
值。
所有值在運行時都只有一種類型,而v
一種靜態類型是interface{}
。接口值由兩個數據字構成:
一個單詞用于指向值的基礎類型的方法表,
另一個詞用于指向該值所持有的實際數據。
附錄:這是Russ的文章在界面結構方面相當完整:
type Stringer interface { String() string}
接口值表示為雙字對,給出指向存儲在接口中的類型的信息的指針和指向相關數據的指針。
將b分配給Stringer類型的接口值會設置接口值的兩個字。
接口值中的第一個單詞指向我稱之為接口表或itable(發音為i-table;在運行時源中,C實現名稱為Itab)。
itable從關于所涉及類型的一些元數據開始,然后成為函數指針的列表。
請注意,itable對應于接口類型,而不是動態類型。
就我們的例子而言,Stringer
持有類型Binary 的itable 列出了用于滿足Stringer的方法,它只是String
:Binary的其他方法(Get
)沒有出現在itable
。接口值中的第二個字指向實際數據,在這種情況下是一個副本
b
。
由于var s Stringer = b
制作副本的原因相同,分配會復制b
而不是指向:如果稍后更改,并且應該具有原始值,而不是新值。 存儲在接口中的值可能是任意大的,但只有一個字專用于將值保存在接口結構中,因此賦值在堆上分配一塊內存并將指針記錄在單字槽中。b
var c uint64 = b
b
s
c

TA貢獻1951條經驗 獲得超3個贊
它被稱為空接口,由所有類型實現,這意味著您可以在該Msg字段中放置任何內容。
示例:
body := Body{3}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:3}
body = Body{"anything"}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:"anything"}
body = Body{body}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:main.Body{Msg:"anything"}}
這是一個類型實現接口的事實的邏輯擴展,只要它具有接口的所有方法。
- 3 回答
- 1 關注
- 1432 瀏覽
添加回答
舉報