我遇到了一个在附加条件下如何递归遍历map [string] interface {}的问题。
1)如果值是映射-递归调用该方法
2)如果值是数组-调用数组的方法
3)如果值不是映射,请对其进行处理。
现在,当方法尝试执行doc.throughMap(mv)
时-发生错误
那么在reflect
确认值是映射或数组之后,如何将某些值转换为所需的类型?
type MapType map[string]interface{}
type ArrayType []interface{}
func (doc *Document) throughMap(docMap MapType) MapType {
for k, v := range docMap {
vt := reflect.TypeOf(v)
switch vt.Kind() {
case reflect.Map:
if mv, ok := v.(map[string]interface{}); ok {
docMap[k] = doc.throughMap(mv)
} else {
panic("error.")
}
case reflect.Array, reflect.Slice:
if mv, ok := v.([]interface{}); ok {
docMap[k] = doc.throughArray(mv)
} else {
panic("error.")
}
default:
docMap[k] = doc.processType(v)
}
}
return docMap
}
Stacktrace:
panic: error. [recovered]
panic: error.
goroutine 1 [running]:
encoding/json.(*encodeState).marshal.func1(0xc000074cd0)
/usr/local/go/src/encoding/json/encode.go:301 +0x9a
panic(0x4bd700, 0x4f9b70)
/usr/local/go/src/runtime/panic.go:513 +0x1b9
project-name/package/name.(*Document).throughMap(0xc00000c028, 0xc000060180, 0xc00007e000)
/home/path/to/project/document.go:231 +0x3f4
project-name/package/name.(*Document).convertDocument(0xc00000c028)
/home/path/to/project/document.go:217 +0x33
project-name/pachage/name.(*Document).MarshalJSON(0xc00000c028, 0x4db740, 0xc00000c028, 0x7f3f0f7540c0, 0xc00000c028, 0xc00001c101)
/home/path/to/project/document.go:167 +0xd8
encoding/json.marshalerEncoder(0xc00007c000, 0x4db740, 0xc00000c028, 0x16, 0xc000070100)
/usr/local/go/src/encoding/json/encode.go:453 +0xb7
encoding/json.(*encodeState).reflectValue(0xc00007c000, 0x4db740, 0xc00000c028, 0x16, 0x4c0100)
/usr/local/go/src/encoding/json/encode.go:333 +0x82
encoding/json.(*encodeState).marshal(0xc00007c000, 0x4db740, 0xc00000c028, 0x4f0100, 0x0, 0x0)
/usr/local/go/src/encoding/json/encode.go:305 +0xf4
encoding/json.Marshal(0x4db740, 0xc00000c028, 0xc000034698, 0x3, 0x3, 0x4d, 0x0)
/usr/local/go/src/encoding/json/encode.go:160 +0x52
main.main()
/home/path/to/project/main.go:21 +0x34d
答案 0 :(得分:1)
关注对我有用
func main() {
x := MapType{
"a": MapType{
"x": MapType{
"p": ArrayType{"l", "o", "l"},
},
} ,
}
d := &Document{}
fmt.Println(d.throughMap(x))
}
type Document struct {}
type MapType map[string]interface{}
type ArrayType []interface{}
func (doc *Document) throughMap(docMap MapType) MapType {
for k, v := range docMap {
fmt.Println(k, v)
vt := reflect.TypeOf(v)
switch vt.Kind() {
case reflect.Map:
if mv, ok := v.(MapType); ok {
docMap[k] = doc.throughMap(mv)
} else {
panic("error.")
}
case reflect.Array, reflect.Slice:
if mv, ok := v.(ArrayType); ok {
docMap[k] = doc.throughArray(mv)
} else {
panic("error.")
}
default:
docMap[k] = doc.processType(v)
}
}
return docMap
}
func (doc *Document) throughArray(arrayType ArrayType) ArrayType {
return arrayType
}
func (doc *Document) processType(x interface{}) interface{} {
return x
}
答案 1 :(得分:1)
使用以下代码遍历任何类型的地图,数组和切片:
func walk(v reflect.Value) {
fmt.Printf("Visiting %v\n", v)
// Indirect through pointers and interfaces
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
v = v.Elem()
}
switch v.Kind() {
case reflect.Array, reflect.Slice:
for i := 0; i < v.Len(); i++ {
walk(v.Index(i))
}
case reflect.Map:
for _, k := range v.MapKeys() {
walk(v.MapIndex(k))
}
default:
// handle other types
}
}