在Go中递归打印映射中的所有值
假设我有一张这种类型的地图:在Go中递归打印映射中的所有值,go,Go,假设我有一张这种类型的地图: var results map[string]interface{} 这些值可以是任何东西,甚至是另一个映射。如何打印所有值?如果该值是一个数组,我想单独打印数组中的每个项目。如果它是另一个地图,我想递归调用地图上的同一个函数。不久前我无耻地从一个网站上撕下了这个: import ( "fmt" "reflect" "strings" ) /* InspectStruct prints the guts of an instantiate
var results map[string]interface{}
这些值可以是任何东西,甚至是另一个映射。如何打印所有值?如果该值是一个数组,我想单独打印数组中的每个项目。如果它是另一个地图,我想递归调用地图上的同一个函数。不久前我无耻地从一个网站上撕下了这个:
import (
"fmt"
"reflect"
"strings"
)
/*
InspectStruct prints the guts of an instantiated struct. Very handy for debugging
usage: InspectStruct(req, 0) -> prints all children
*/
func InspectStructV(val reflect.Value, level int) {
if val.Kind() == reflect.Interface && !val.IsNil() {
elm := val.Elem()
if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
val = elm
}
}
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
typeField := val.Type().Field(i)
address := "not-addressable"
if valueField.Kind() == reflect.Interface && !valueField.IsNil() {
elm := valueField.Elem()
if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
valueField = elm
}
}
if valueField.Kind() == reflect.Ptr {
valueField = valueField.Elem()
}
if valueField.CanAddr() {
address = fmt.Sprintf("0x%X", valueField.Addr().Pointer())
}
fmt.Printf("%vField Name: %s,\t Field Value: %v,\t Address: %v\t, Field type: %v\t, Field kind: %v\n",
strings.Repeat("\t", level),
typeField.Name,
//valueField.Interface(),
address,
typeField.Type,
valueField.Kind())
if valueField.Kind() == reflect.Struct {
InspectStructV(valueField, level+1)
}
}
}
func InspectStruct(v interface{}, level int) {
InspectStructV(reflect.ValueOf(v), level)
}
导入(
“fmt”
“反映”
“字符串”
)
/*
InspectStruct打印实例化结构的内部。非常方便调试
用法:InspectStruct(req,0)->打印所有子项
*/
func InspectStructV(val reflect.Value,级别int){
如果val.Kind()==reflect.Interface&!val.IsNil(){
elm:=val.Elem()
如果elm.Kind()==reflect.Ptr&&!elm.IsNil()&&elm.Elem().Kind()==reflect.Ptr{
瓦尔=埃尔姆
}
}
如果val.Kind()==reflect.Ptr{
val=val.Elem()
}
对于i:=0;i
在fmt上使用%v。Printf将遍历内部映射并打印元素
也可以通过对每个字符串调用String()。现在,如果要更改内部类型的默认打印,只需在该类型上实现String()。在下面的示例中,我创建了[]int的一个版本,它每行打印一个int
package main
import (
"fmt"
"strings"
)
type OnePerLineInt []int
func (ip OnePerLineInt) String() string {
var ret []string
for _, a := range ip {
ret = append(ret, fmt.Sprintf("Item: %v\n", a))
}
return strings.Join(ret, "")
}
func main() {
arr := &OnePerLineInt{1, 2, 3}
arr1 := []int{4, 5 , 6}
foo := make(map[string]interface{})
bar := make(map[string]interface{})
bar["a"] = "foobar1"
bar["b"] = "foobar2"
foo["1"] = arr
foo["2"] = bar
foo["3"] = arr1
fmt.Printf("foo contents: %v\n", foo)
fmt.Printf("bar is :%v\n", bar)
}
印刷品:
foo contents: map[1:Item: 1
Item: 2
Item: 3
2:map[a:foobar1 b:foobar2] 3:[4 5 6]]
bar is :map[a:foobar1 b:foobar2]
您是否只想打印它以检查其中的数据?您是否尝试过
fmt
软件包提供的各种输出?封送到json对您有用吗?@sberry我不想检查其中的数据,我只想比较两个任意json哈希的值并打印出交叉点。@JimB是的,我将json封送到这种格式,因为数据是任意的。@VladtheImpala您的评论和问题不匹配谢谢,关键是reflect.TypeOf(value).Kind()==reflect.Map
@VladtheImpala注意:使用Go 1.5打印reflect.value()会更容易。看,你能指出应该如何使用它吗?当我使用InspectStruct(myMap,1)
时,它会在映射值上给出错误reflect.Value.NumField
@bat,应该这样使用,但它不是100%故障保存。我不得不时不时地禁用一些线路,以便在特定的有效负载下工作。