我正在尝试创建一个可以接受以下功能的函数
*struct []*struct map[string]*struct
这里的struct可以是任何结构,而不仅仅是特定的结构。将接口转换为*struct或[]*struct工作正常。但是给地图错误。
*struct
[]*struct
反映后显示为map [],但尝试在范围内进行迭代时给出错误。
这是代码
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) }
有什么方法可以转换interface{}为map并进行迭代或获取其元素。
interface{}
如果地图值可以是任何类型,则使用反射来遍历地图:
if v.Kind() == reflect.Map { for _, key := range v.MapKeys() { strct := v.MapIndex(key) fmt.Println(key.Interface(), strct.Interface()) } }
游乐场的例子
如果存在少量已知的结构类型,则可以使用类型开关:
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 } }