1 回答

TA貢獻1831條經驗 獲得超4個贊
如果將變量聲明為 type?interface{}
,則它就是type?interface{}
。它永遠不具有map[keytype]valuetype
某種價值。但是類型變量interface{}
可以保存具有其他具體類型的值。當它這樣做時,它就這樣做——僅此而已。它仍然是type?interface{}
,但它包含其他類型的值。
接口值由兩部分組成
這里的關鍵區別在于interface{}
變量是什么以及它包含什么。任何接口變量實際上都有兩個槽:一個用于保存其中存儲的類型,另一個用于保存其中存儲的值。每當您(或任何人)為變量賦值時,編譯器都會填充兩個槽:類型(來自您使用的值的類型)和值(來自您使用的值)。1nil
如果接口變量在兩個槽中 都有,則比較等于 nil?;這也是默認的零值。
因此,您的運行時測試:
valueMap,?ok?:=?myMap.(map[string]interface{})
是明智的做法:如果myMap
持有一個類型為 的值map[string]interface
,ok
則將其設置為true
并valueMap
包含該值(具有該類型)。如果myMap
持有某個其他類型的值,ok
則設置為false
并valueMap
設置為 類型的零值map[string]interface{}
。換句話說,在運行時,代碼首先檢查類型槽,然后將值槽復制到valueMap
并設置ok
為 true,或者設置valueMap
為nil
并設置ok
為 false。
如果且當ok
已設置為時true
,每個valueMap[k]
值都是type?interface{}
。和以前一樣,對于myMap
其本身,每個interface{}
變量都可以(但不必)保存 type 的值string
,并且您必須使用某種“實際類型和值是什么”運行時測試來區分它們。
當您將json.Unmarshal
解碼后的 JSON 填充到 類型的變量中時interface{}
,它能夠反序列化任何這些記錄的 JSON 類型。然后該列表告訴您什么類型被填充到接口變量中:
bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null
因此,在執行json.Unmarshal完類型為 的變量之后interface{},您應該檢查變量的類型槽中放入的類型。您可以使用斷言和ok布爾值來完成此操作,或者如果您愿意,也可以使用類型開關對其進行解碼:
var i interface
if err := json.Unmarshal(data, &i); err != nil {
? ? panic(err)
}
switch v := i.(type) {
case string:
? ? ... code ...
case map[string]interface{}:
? ? ... code ...
... add some or all of the types listed ...
}
問題是,無論您在此處的代碼中執行什么操作,您都確實已將某些json.Unmarshal內容放入interface{}, 并且interface{} 是的類型i。您必須在運行時測試接口保存的類型和值對。
您的另一個選擇是手動檢查 JSON 字符串并決定提供給 的變量類型json.Unmarshal。這使得您可以在后面編寫更少的代碼,但在 之前Unmarshal編寫更多代碼。
在 Go Playground 上有一個更完整的示例,使用類型開關來檢查json.Unmarshal. 它故意不完整,但我認為,有足夠的輸入和輸出案例,可以讓您了解如何處理所有內容,考慮到上面關于寫入類型變量的內容的json.Unmarshal引用interface{}。
1當然,如果您interface{}從其他地方分配一個interface{}:
var i1, i2 interface{}
... set i1 from some actual value ...
// more code, then:
i2 = i1
編譯器只是將兩個槽從 復制i1到i2。當你這樣做時,兩個獨立插槽的事情就會變得更加清晰:
var f float64
... code that sets f to, say, 1.5 ...
i2 = f
例如,當寫入float64類型槽時,將值1.5寫入值槽中。編譯器知道這f一點,float64因此類型設置只是意味著“在其中粘貼一個常量”。編譯器不一定知道的值f,因此值設置是實際值的副本。
- 1 回答
- 0 關注
- 171 瀏覽
添加回答
舉報