我有一些關于介面的問題,特別是當這些介面在函式之間傳遞的時候。
我理解介面是隱式滿足的,也就是說下面的代碼是有效的:
我理解介面是隱式滿足的。
type itemX struct {}。
func (x *itemX) Do() string {
return " itemX"
}
type Itf interface {
Do() string
}
func test(i Itf) string {
return i.Do()
}
func main() {
x := new( itemX )。
str := test(x) //有效,因為x隱含地滿足Itf。
}
然而,當我開始在函式之間傳遞介面時,會發生什么或型別契約是什么并不清楚。一個例子:
// itemX、Itf和test的宣告與上面的片段相同。
func returnsItf(i Itf) Itf {
return i
}
func returnsTypeAssertedX(i Itf) Itf {
return i. (*itemX)
}
func takeItf(i Itf) {}。
func takeX(x *itemX) {}
func main() {
x := new( itemX )。
var i Itf = x
a := returnsItf(i) //回傳Itf型別。
_ = takeItf(a) //沒有錯誤。
b := returnsTypeAssertedX(i)
_ = takeItf(b) //沒有錯誤,因為*itemX實作了Itf。
_ = takeX(b) //錯誤,不能使用b (type Itf as *itemX)。
}
當一個介面作為一個函式回傳傳遞出去時,似乎有一些隱藏的行為。如果回傳是*itemX并且型別是Itf,那么在函式框架終止之前,回傳將被轉換為Itf。
因此,這個隱含的檢查(具體的->介面,如果型別是介面)在每個函式呼叫中要進行兩次:
- 在每個函式開始時
- 在每個函式呼叫的開始,
- 和結束。
- 和結束時。
我對這種隱式轉換的理解是否正確?
uj5u.com熱心網友回復:
一個介面是一個有兩個成員的資料型別。底層物件的型別,以及指向該物件的指標。因此,當你在一個需要介面的背景關系中使用一個非介面型別時,編譯器會從該值中構造一個介面型別,并使用該介面。
func returnsTypeAssertedX(i Itf) Itf {
return i. (*itemX)
}
在上面的函式中,它首先對傳入的引數進行型別確認,并將引數的底層值轉換回一個介面。
b := returnsTypeAssertedX(i)
_ = takeX(b)
上面的方法將無法作業,因為b是一個interface{},而takeX需要一個*itemX。然而,這樣做也可以:
takeX(b.(*itemX)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/313776.html
標籤:
上一篇:為什么Golanghchan結構的封閉欄位使用uint32型別?
下一篇:為什么在gin的*Context.Render(codeint,rrender.Render)方法中首先設定回應代碼?
