将接口{}转换为Golang中的map

时间:2016-07-04 13:25:58

标签: dictionary reflection go interface

我正在尝试创建一个可以接受以下

的函数
    var elems= document.querySelectorAll('[name=feature[]')
                for (var i=0;i<elems.length;i++)
                {
                    var isChecked =elems[i].checked;
                    console.log(isChecked);
                }

这里struct可以是任何结构,而不仅仅是特定结构。 将界面转换为*struct []*struct map[string]*struct *struct工作正常。 但是为地图提供错误。

反映后显示它是map [],但在尝试迭代范围时给出错误。

这是代码

[]*struct

有没有办法将package main import ( "fmt" "reflect" ) type Book struct { ID int Title string Year int } func process(in interface{}, isSlice bool, isMap bool) { v := reflect.ValueOf(in) if isSlice { for i := 0; i < v.Len(); i++ { strct := v.Index(i).Interface() //... proccess struct } return } if isMap { fmt.Printf("Type: %v\n", v) // map[] for _, s := range v { // Error: cannot range over v (type reflect.Value) fmt.Printf("Value: %v\n", s.Interface()) } } } func main() { b := Book{} b.Title = "Learn Go Language" b.Year = 2014 m := make(map[string]*Book) m["1"] = &b process(m, false, true) } 转换成地图并迭代或获取它的元素。

4 个答案:

答案 0 :(得分:22)

如果地图值可以是任何类型,则使用reflect来迭代地图:

if v.Kind() == reflect.Map {
    for _, key := range v.MapKeys() {
        strct := v.MapIndex(key)
        fmt.Println(key.Interface(), strct.Interface())
    }
}

playground example

如果有一组很小且已知的结构类型,那么可以使用type switch

func process(in interface{}) {
  switch v := in.(type) {
  case map[string]*Book:
     for s, b := range v {
         // b has type *Book
         fmt.Printf("%s: book=%v\n" s, b)
     }
  case map[string]*Author:
     for s, a := range v {
         // a has type *Author
         fmt.Printf("%s: author=%v\n" s, a)
     }
   case []*Book:
     for i, b := range v {
         fmt.Printf("%d: book=%v\n" i, b)
     }
   case []*Author:
     for i, a := range v {
         fmt.Printf("%d: author=%v\n" i, a)
     }
   case *Book:
     fmt.Ptintf("book=%v\n", v)
   case *Author:
     fmt.Printf("author=%v\n", v)
   default:
     // handle unknown type
   }
}

答案 1 :(得分:19)

你不需要在这里反思。尝试:

v, ok := in.(map[string]*Book)
if !ok {
    // Can't assert, handle error.
}
for _, s := range v {
    fmt.Printf("Value: %v\n", s)
}

其余的功能也是如此。当type switch为您提供更好的服务时,您似乎正在使用反射。

或者,如果你坚持在这里使用反射(这没有多大意义),你也可以使用Value.MapKeys和ValueOf的结果(参见答案https://stackoverflow.com/a/38186057/714501

答案 2 :(得分:0)

使用包反射将 interface{} 转换为 map 的另一种方法是使用 MapRange

我引用:

<块引用>

MapRange 返回地图的范围迭代器。如果 v 的 Kind 是,它会恐慌 不是地图。

调用 Next 来推进迭代器,调用 Key/Value 来访问每个条目。 当迭代器耗尽时,Next 返回 false。地图范围如下 与范围语句相同的迭代语义。

示例:

iter := reflect.ValueOf(m).MapRange()
for iter.Next() {
    key := iter.Key().Interface()
    value := iter.Value().Interface()
    ...
}

答案 3 :(得分:0)

这可能会有所帮助:

b := []byte(`{"keyw":"value"}`)

var f interface{}
json.Unmarshal(b, &f)

myMap := f.(map[string]interface{})

fmt.Println(myMap)