如何将 interface 转换为地图
Posted
技术标签:
【中文标题】如何将 interface 转换为地图【英文标题】:How to convert interface to map如何将 interface 转换为地图 【发布时间】:2016-11-06 06:09:39 【问题描述】:我正在尝试创建一个可以接受关注的函数
*struct
[]*struct
map[string]*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
转换为映射和迭代或获取它的元素。
【问题讨论】:
【参考方案1】:这可能会有所帮助:
b := []byte(`"keyw":"value"`)
var f interface
json.Unmarshal(b, &f)
myMap := f.(map[string]interface)
fmt.Println(myMap)
【讨论】:
【参考方案2】:使用反射包将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】:如果地图值可以是任何类型,则使用反射来遍历地图:
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
【讨论】:
不错。当您发布您的答案时,我将MapKeys
添加到我的答案部分!
工作得很好。非常感谢。【参考方案4】:
你不需要在这里反思。试试:
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://***.com/a/38186057/714501)
【讨论】:
这里的结构可以是任何结构,如 Book、Auther、Publisher ... 用于类型切换的结构类型必须是已知的,我没有。 @SamTech 结构的类型如何不“已知”?您可以切换您想要处理的所有类型。 我的意思是,我怎么知道我是否必须输入 switch 传递的接口到 map[string]*Book 或 map[string]*Auther ? @SamTech 两者都打开。以上是关于如何将 interface 转换为地图的主要内容,如果未能解决你的问题,请参考以下文章
UIView 的子类。如何通过 Interface Builder 添加?