英文:
Print interface map with types
问题
我有一个函数,它接收一些字节并将它们解析成一个映射。我想打印出这个映射,如果可能的话,还要包含类型信息。我尝试了以下代码:
package main
import "fmt"
func main() {
m := map[string]interface{}{
"one": uint16(1), "two": map[string]interface{}{
"three": uint32(3), "four": uint64(4),
},
}
/*
map[string]interface {}{
"one":0x1, "two":map[string]interface {}{"four":0x4, "three":0x3}
}
*/
fmt.Printf("%#v\n", m)
}
但它没有打印出数字类型。我可以这样做:
// uint16
fmt.Printf("%T\n", m["one"])
但是映射可能很大,所以我想避免手动打印每个值。我想知道是否有可能实现我想要的效果?
英文:
I have a function that takes in some bytes, and parses them into a map. I would
like to print out this map, but with the types included if possible. I tried
this:
package main
import "fmt"
func main() {
m := map[string]interface{}{
"one": uint16(1), "two": map[string]interface{}{
"three": uint32(3), "four": uint64(4),
},
}
/*
map[string]interface {}{
"one":0x1, "two":map[string]interface {}{"four":0x4, "three":0x3}
}
*/
fmt.Printf("%#v\n", m)
}
but it doesnt print out the number types. I can do this:
// uint16
fmt.Printf("%T\n", m["one"])
but the map can be pretty big, so I would like to avoid having to manually print
every value. Is it possible to do what I am wanting?
答案1
得分: 3
使用for循环和递归打印地图值的类型:
func printTypes(m map[string]interface{}, indent string) {
for k, v := range m {
fmt.Printf("%s%s: %T\n", indent, k, v)
// 如果值是嵌套地图,则递归调用
if m, ok := v.(map[string]interface{}); ok {
printTypes(m, indent+" ")
}
}
}
// 调用方式如下:
printTypes(m, "")
这段代码的作用是遍历一个地图(map)的键值对,并打印出每个值的类型。如果值是一个嵌套的地图,则会递归调用函数来打印嵌套地图中的值类型。
英文:
Use for loops and recursion to print map values types:
func printTypes(m map[string]interface{}, indent string) {
for k, v := range m {
fmt.Printf("%s%s: %T\n", indent, k, v)
// Recurse if value is a nested map
if m, ok := v.(map[string]interface{}); ok {
printTypes(m, indent+" ")
}
}
}
Call it like this:
printTypes(m, "")
答案2
得分: 1
如果你能控制地图的创建,你可以使用自定义类型代替:
package object
import "fmt"
type (
Uint16 uint16
Uint32 uint32
Uint64 uint64
)
func (u Uint16) GoString() string {
return fmt.Sprintf("uint16(%v)", uint16(u))
}
func (u Uint32) GoString() string {
return fmt.Sprintf("uint32(%v)", uint32(u))
}
func (u Uint64) GoString() string {
return fmt.Sprintf("uint64(%v)", uint64(u))
}
或者,你可以覆盖整个地图:
package object
import "fmt"
type object map[string]interface{}
func (o object) GoString() string {
str := "map[string]interface{}{"
first := true
for key, val := range o {
if first {
first = false
} else {
str += ","
}
str += fmt.Sprintf("%q:", key)
switch typ := val.(type) {
case uint16:
str += fmt.Sprintf("uint16(%v)", typ)
case uint32:
str += fmt.Sprintf("uint32(%v)", typ)
case uint64:
str += fmt.Sprintf("uint64(%v)", typ)
default:
str += fmt.Sprintf("%#v", val)
}
}
return str + "}"
}
https://godocs.io/fmt#GoStringer
英文:
If you are able to control the creation of the map, you can use custom types
instead:
package object
import "fmt"
type (
Uint16 uint16
Uint32 uint32
Uint64 uint64
)
func (u Uint16) GoString() string {
return fmt.Sprintf("uint16(%v)", uint16(u))
}
func (u Uint32) GoString() string {
return fmt.Sprintf("uint32(%v)", uint32(u))
}
func (u Uint64) GoString() string {
return fmt.Sprintf("uint64(%v)", uint64(u))
}
Or, you can override the whole map:
package object
import "fmt"
type object map[string]interface{}
func (o object) GoString() string {
str := "map[string]interface{}{"
first := true
for key, val := range o {
if first {
first = false
} else {
str += ","
}
str += fmt.Sprintf("%q:", key)
switch typ := val.(type) {
case uint16:
str += fmt.Sprintf("uint16(%v)", typ)
case uint32:
str += fmt.Sprintf("uint32(%v)", typ)
case uint64:
str += fmt.Sprintf("uint64(%v)", typ)
default:
str += fmt.Sprintf("%#v", val)
}
}
return str + "}"
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论