我發現它很奇怪,爲什麼[]字符串不能轉換爲[] interface {}?爲什麼[]字符串無法轉換爲[] interface {} in golang
我覺得應該是有可能的,因爲:
- 他們都是片
- 的[]字符串是字符串,這當然是接口{}
,但在每一個元素下面的例子,這將是一個編譯錯誤
func f(args ...interface{}){
}
s := []string{"ssd", "rtt"}
f(s...)
爲什麼語言無法完成自動轉換?
我發現它很奇怪,爲什麼[]字符串不能轉換爲[] interface {}?爲什麼[]字符串無法轉換爲[] interface {} in golang
我覺得應該是有可能的,因爲:
,但在每一個元素下面的例子,這將是一個編譯錯誤
func f(args ...interface{}){
}
s := []string{"ssd", "rtt"}
f(s...)
爲什麼語言無法完成自動轉換?
因爲[]string
和[]interface{}
具有不同的內存中佈局。當你意識到interface{}
變量需要知道它包含的值的類型時,這是顯而易見的。
對於[]string
切片,後備陣列只需要保存單個字符串。對於[]interface{}
切片,您同時具有類型信息和字符串值(以及指向字符串值的指針,因爲字符串比單個內存字大)。因此,從一種類型轉換到另一種類型將涉及複製數據。
Go會自動執行轉換會令人困惑,因爲它會導致難以推理代碼。例如,函數調用f(s)
可以修改片段s
中的字符串,前提是它聲明採用[]string
參數,但如果聲明採用[]interface{}
參數,則不會修改該片段中的字符串。
切片基本上只是對底層數組,開始指針,長度和容量的引用。因此,如果可能的話,請考慮以下幾點:
sliceOfStrings := []string{"one", "two", "three"}
// prints ONE TWO THREE
for i := range sliceOfStrings {
fmt.Println(strings.ToUpper(sliceOfStrings[i]))
}
// imagine this is possible
var sliceOfInterface = []interface{}(sliceOfStrings)
// since it's array of interface{} now - we can do anything
// let's put integer into the first position
sliceOfInterface[0] = 1
// sliceOfStrings still points to the same array, and now "one" is replaced by 1
fmt.Println(strings.ToUpper(sliceOfStrings[0])) // BANG!
此問題存在於Java和C#中。實際上它很少發生,但仍然如此。假設在Go中不存在像int32 - > int64這樣的自動類型轉換,如果您確實想將[] string作爲[] interface {}發送,那麼您可以強制創建[] interface {}副本。這樣就不會有什麼驚喜 - 你明確地寫出來了,你知道你在做什麼。如果函數將修改[] interface {} - 它不會傷害原始[]字符串。
Golang數組不支持協方差 - 請參閱http://stackoverflow.com/questions/3839335/any-sensible-solution-to-the-lack-of-array-slice-covariance-in-go?rq=1 ,http://stackoverflow.com/questions/19389629/golang-go-get-the-type-of-array – user2864740
這在FAQ http://golang.org/doc/faq#convert_slice_of_interface中有描述。閱讀golang.org上提供的文檔不能過度推薦。 – Volker
http://stackoverflow.com/q/12990338/727643的副本 –