1 回答

TA貢獻(xiàn)1831條經(jīng)驗(yàn) 獲得超4個(gè)贊
如果將變量聲明為 type?interface{}
,則它就是type?interface{}
。它永遠(yuǎn)不具有map[keytype]valuetype
某種價(jià)值。但是類型變量interface{}
可以保存具有其他具體類型的值。當(dāng)它這樣做時(shí),它就這樣做——僅此而已。它仍然是type?interface{}
,但它包含其他類型的值。
接口值由兩部分組成
這里的關(guān)鍵區(qū)別在于interface{}
變量是什么以及它包含什么。任何接口變量實(shí)際上都有兩個(gè)槽:一個(gè)用于保存其中存儲(chǔ)的類型,另一個(gè)用于保存其中存儲(chǔ)的值。每當(dāng)您(或任何人)為變量賦值時(shí),編譯器都會(huì)填充兩個(gè)槽:類型(來(lái)自您使用的值的類型)和值(來(lái)自您使用的值)。1nil
如果接口變量在兩個(gè)槽中 都有,則比較等于 nil?;這也是默認(rèn)的零值。
因此,您的運(yùn)行時(shí)測(cè)試:
valueMap,?ok?:=?myMap.(map[string]interface{})
是明智的做法:如果myMap
持有一個(gè)類型為 的值map[string]interface
,ok
則將其設(shè)置為true
并valueMap
包含該值(具有該類型)。如果myMap
持有某個(gè)其他類型的值,ok
則設(shè)置為false
并valueMap
設(shè)置為 類型的零值map[string]interface{}
。換句話說,在運(yùn)行時(shí),代碼首先檢查類型槽,然后將值槽復(fù)制到valueMap
并設(shè)置ok
為 true,或者設(shè)置valueMap
為nil
并設(shè)置ok
為 false。
如果且當(dāng)ok
已設(shè)置為時(shí)true
,每個(gè)valueMap[k]
值都是type?interface{}
。和以前一樣,對(duì)于myMap
其本身,每個(gè)interface{}
變量都可以(但不必)保存 type 的值string
,并且您必須使用某種“實(shí)際類型和值是什么”運(yùn)行時(shí)測(cè)試來(lái)區(qū)分它們。
當(dāng)您將json.Unmarshal
解碼后的 JSON 填充到 類型的變量中時(shí)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
因此,在執(zhí)行json.Unmarshal完類型為 的變量之后interface{},您應(yīng)該檢查變量的類型槽中放入的類型。您可以使用斷言和ok布爾值來(lái)完成此操作,或者如果您愿意,也可以使用類型開關(guān)對(duì)其進(jìn)行解碼:
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 ...
}
問題是,無(wú)論您在此處的代碼中執(zhí)行什么操作,您都確實(shí)已將某些json.Unmarshal內(nèi)容放入interface{}, 并且interface{} 是的類型i。您必須在運(yùn)行時(shí)測(cè)試接口保存的類型和值對(duì)。
您的另一個(gè)選擇是手動(dòng)檢查 JSON 字符串并決定提供給 的變量類型json.Unmarshal。這使得您可以在后面編寫更少的代碼,但在 之前Unmarshal編寫更多代碼。
在 Go Playground 上有一個(gè)更完整的示例,使用類型開關(guān)來(lái)檢查json.Unmarshal. 它故意不完整,但我認(rèn)為,有足夠的輸入和輸出案例,可以讓您了解如何處理所有內(nèi)容,考慮到上面關(guān)于寫入類型變量的內(nèi)容的json.Unmarshal引用interface{}。
1當(dāng)然,如果您interface{}從其他地方分配一個(gè)interface{}:
var i1, i2 interface{}
... set i1 from some actual value ...
// more code, then:
i2 = i1
編譯器只是將兩個(gè)槽從 復(fù)制i1到i2。當(dāng)你這樣做時(shí),兩個(gè)獨(dú)立插槽的事情就會(huì)變得更加清晰:
var f float64
... code that sets f to, say, 1.5 ...
i2 = f
例如,當(dāng)寫入float64類型槽時(shí),將值1.5寫入值槽中。編譯器知道這f一點(diǎn),float64因此類型設(shè)置只是意味著“在其中粘貼一個(gè)常量”。編譯器不一定知道的值f,因此值設(shè)置是實(shí)際值的副本。
- 1 回答
- 0 關(guān)注
- 185 瀏覽
添加回答
舉報(bào)