亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何檢查聲明為map[string]interface{}的變量實際上是mapstring?

如何檢查聲明為map[string]interface{}的變量實際上是mapstring?

Go
aluckdog 2023-07-31 16:47:36
我有一個變量需要是 astring或map[string]string(將從 JSON 反序列化)。所以我將其聲明為interface{}.?我如何檢查該值是否為map[string]string?僅在變量聲明為map[string]stringnot 且變量為 的情況下才有效interface{}。package mainimport (? ? "fmt")func main() {? ? var myMap interface{}? ? myMap = map[string]interface{}{? ? ? ? "foo": "bar",? ? }? ? _, ok := myMap.(map[string]string)? ? if !ok {? ? ? ? fmt.Println("This will be printed")? ? }}請參閱https://play.golang.org/p/mA-CVk7bdb9不過我可以使用兩種類型斷言。一張在地圖上,一張在地圖上的值。package mainimport (? ? "fmt")func main() {? ? var myMap interface{}? ? myMap = map[string]interface{}{? ? ? ? "foo": "bar",? ? }? ? valueMap, ok := myMap.(map[string]interface{})? ? if !ok {? ? ? ? fmt.Println("will not be printed")? ? }? ? for _, v := range valueMap {? ? ? ? if _, ok := v.(string); !ok {? ? ? ? ? ? fmt.Println("will not be printed")? ? ? ? }? ? }}問:有更好的辦法嗎?
查看完整描述

1 回答

?
慕容708150

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則將其設置為truevalueMap包含該值(具有該類型)。如果myMap持有某個其他類型的值,ok則設置為falsevalueMap設置為 類型的零值map[string]interface{}。換句話說,在運行時,代碼首先檢查類型槽,然后將值槽復制到valueMap并設置ok為 true,或者設置valueMapnil并設置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,因此值設置是實際值的副本。


查看完整回答
反對 回復 2023-07-31
  • 1 回答
  • 0 關注
  • 171 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號