迭代接口映射的值

Iterate over values of map of interfaces

如何遍历下面的接口映射以获取映射中返回的接口值?

我已经通读了有关 Go 中迭代的大量问题列表,但它们对我没有帮助。

// https://api.kraken.com/0/public/AssetPairs

pairsResult, err := api.Query("AssetPairs", map[string]string{
})

if err != nil {
    log.Fatal(err)
}

ks := reflect.ValueOf(pairsResult).MapKeys()

fmt.Printf(" %+v ", pairsResult) // result A below
fmt.Printf(" %+v ", ks) // result B below

// the value here is the value of MapKeys, which is the key
for kix, key := range ks {
    fmt.Printf(" %+v %+v \n ", kix, key) // result C below
}

结果A

map[AAVEETH:map[aclass_base:currency aclass_quote:currency altname:AAVEETH base:AAVE fee_volume_currency:ZUSD fees:[[0 0.26] [50000 0.24] [100000 0.22] [250000 0.2] [500000 0.18]...

结果 B

[KEEPXBT LINKUSD LINKXBT NANOEUR ...]

结果 C

0 KEEPXBT 1 LINKUSD 2 LINKXBT 3 NANOEUR 4 USDTAUD ...

这是上面调用的 API 包装函数的来源

// Query sends a query to Kraken api for given method and parameters
func (api *KrakenAPI) Query(method string, data map[string]string) (interface{}, error) {
    values := url.Values{}
    for key, value := range data {
        values.Set(key, value)
    }

    // Check if method is public or private
    if isStringInSlice(method, publicMethods) {
        return api.queryPublic(method, values, nil)
    } else if isStringInSlice(method, privateMethods) {
        return api.queryPrivate(method, values, nil)
    }

    return nil, fmt.Errorf("Method '%s' is not valid", method)
}

当我尝试迭代值时会发生这种情况:

当我尝试迭代初始结果时会发生这种情况:

假设您正在使用 this 并且通过查看它的来源,在我看来,结果的具体类型将是 map[string]interface{},如果是这样,那么您可以这样做。

res, err := api.Query("AssetPairs", map[string]string{})
if err != nil {
    log.Fatal(err)
}

pairs, ok := res.(map[string]interface{})
if !ok {
    log.Fatal("unsupported type")
}

for k, v := range pairs {
    fmt.Printf("key=%s value=%+v\n ", k, v)
}

正如前面的回复提到的,我们看到返回的接口变成了 map[string]interface{},下面的代码可以用来检索类型:

    for _, v := range d.(map[string]interface{}) {
        switch v.(type) {
        case map[string]interface{}:
            fmt.Println("Its another map of string interface")
        case interface{}:
            fmt.Println("its an interface")
        case string:
            fmt.Println("its a string")
        case []string:
            fmt.Println("its a string array")
        case float32:
            fmt.Println("its a float32")
        case float64:
            fmt.Println("its a float64")
        default:
            fmt.Printf("Different thing, %T\n", v)
        }
    }

代码在这里: https://play.golang.org/p/81LLYSvJVf8

但是,我建议使用显式类型,这会让您的生活更轻松:

// Generated by https://quicktype.io

type KrakenTypes struct {
    Error  []interface{}     `json:"error"` 
    Result map[string]Result `json:"result"`
}

type Result struct {
    Altname           string            `json:"altname"`            
    Wsname            *string           `json:"wsname,omitempty"`   
    AclassBase        Aclass            `json:"aclass_base"`        
    Base              string            `json:"base"`               
    AclassQuote       Aclass            `json:"aclass_quote"`       
    Quote             FeeVolumeCurrency `json:"quote"`              
    Lot               Lot               `json:"lot"`                
    PairDecimals      int64             `json:"pair_decimals"`      
    LotDecimals       int64             `json:"lot_decimals"`       
    LotMultiplier     int64             `json:"lot_multiplier"`     
    LeverageBuy       []int64           `json:"leverage_buy"`       
    LeverageSell      []int64           `json:"leverage_sell"`      
    Fees              [][]float64       `json:"fees"`               
    FeesMaker         [][]float64       `json:"fees_maker"`         
    FeeVolumeCurrency FeeVolumeCurrency `json:"fee_volume_currency"`
    MarginCall        int64             `json:"margin_call"`        
    MarginStop        int64             `json:"margin_stop"`        
    Ordermin          *string           `json:"ordermin,omitempty"` 
}

这里我们可以在读取响应后使用json解码,这样就可以避免迭代找出每个级别的类型,我们可以直接访问每个成员。

完整代码在这里:https://play.golang.org/p/v3tlroyx1mW