打印带有类型的接口映射。

huangapple go评论164阅读模式
英文:

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 + "}"
}

https://godocs.io/fmt#GoStringer

huangapple
  • 本文由 发表于 2021年12月1日 05:11:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/70176114.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定