Go Wiki:InterfaceSlice
簡介
假設您可以將任何類型的變數指定給 interface{}
,人們通常會嘗試以下類型的程式碼。
var dataSlice []int = foo()
var interfaceSlice []interface{} = dataSlice
這會產生錯誤
cannot use dataSlice (type []int) as type []interface { } in assignment
因此,問題是「當我可以將任何類型指定給 interface{}
時,為何無法將任何陣列指定給 []interface{}
?」
原因為何?
這有兩個主要原因。
第一個是類型為 []interface{}
的變數不是介面!它是一個切片,其元素類型恰好為 interface{}
。但即使如此,有人可能會說意思很清楚。
好吧,真的是嗎?類型為 []interface{}
的變數具有在編譯時已知的特定記憶體配置。
每個 interface{}
佔用兩個字元(一個字元表示所包含內容的類型,另一個字元表示所包含資料或指向它的指標)。因此,長度為 N 且類型為 []interface{}
的切片由 N*2 個字元長的資料塊做為後盾。
這與具有類型 []MyType
和相同長度的切片所支援的資料塊不同。其資料塊將為 N*sizeof(MyType) 個字元長。
結果是您無法快速將類型為 []MyType
的內容指定給類型為 []interface{}
的內容;它們背後的資料看起來就是不一樣。
我還能做什麼?
這取決於您最初想要做什麼。
如果您想要一個任意陣列類型的容器,並且您計畫在執行任何索引作業之前變回原始類型,您可以只使用 interface{}
。該程式碼將是通用的(如果不是編譯時類型安全的話),而且快速。
如果您真的想要一個 []interface{}
,因為您會在轉換回之前進行索引,或者您正在使用特定的介面類型並且您想要使用它的方法,您將必須複製切片。
var dataSlice []int = foo()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
interfaceSlice[i] = d
}
此內容是 Go Wiki 的一部分。