V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
ysmood
V2EX  ›  Go 编程语言

分享一个用于打印复杂数据结构的库 gop

  •  1
     
  •   ysmood ·
    ysmood · 2022-03-22 15:57:20 +08:00 · 5444 次点击
    这是一个创建于 996 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目地址 https://github.com/ysmood/got/tree/master/lib/gop

    目的是把复杂的结构体打印成易于阅读的格式。输出的格式使用的 Go 原生语法,不需要学习任何额外的知识就可以阅读输出。不像其他库可能需要考猜测输出格式。

    特性

    • 使用原生 Go 语法输出
    • 支持循环引用(比如 go-spew 的这个 bug, 而 gop 可以正常打印)
    • 更好的 rune, []byte, time 等数据的可读性
    • 字符串里的隐藏字符也会被打印
    • 可配置的高亮打印
    • 根据排序后的 key 输出一致的 map
    • 自动将多行大段文字打印成多行以便于阅读
    • 可扩展的 API

    用法

    通常你只需要用 gop.P 函数:

    package main
    
    import (
        "time"
    
        "github.com/ysmood/got/lib/gop"
    )
    
    func main() {
        val := map[string]interface{}{
            "bool":   true,
            "number": 1 + 1i,
            "bytes":  []byte{97, 98, 99},
            "lines":  "multiline string\nline two",
            "slice":  []interface{}{1, 2},
            "time":   time.Now(),
            "struct": struct{ test int32 }{
                test: 13,
            },
        }
        val["slice"].([]interface{})[1] = val["slice"]
    
        gop.P(val)
    }
    

    输出:

    11 条回复    2022-03-30 10:36:22 +08:00
    tairan2006
        1
    tairan2006  
       2022-03-22 21:36:51 +08:00
    支持打印指针成员么?感觉平时%+v 最大的问题就是无法输出指针成员…要自己写 Stringer
    ysmood
        2
    ysmood  
    OP
       2022-03-23 00:54:34 +08:00 via Android
    @tairan2006 支持
    eudore
        3
    eudore  
       2022-03-23 10:01:23 +08:00
    造过一个差不多的轮子,支持:godoc 链接跳转 层次路径访问 json/text/html 三种数据格式 html 显示对象折叠 设置显示私有和最大层数
    ysmood
        4
    ysmood  
    OP
       2022-03-23 10:21:48 +08:00
    @eudore html 的问题主要是 CI 的 log 里 debug 比较麻烦。
    FlyingDough
        5
    FlyingDough  
       2022-03-23 11:29:41 +08:00
    已 star
    rekulas
        6
    rekulas  
       2022-03-23 12:26:17 +08:00
    cool
    Redamancy
        7
    Redamancy  
       2022-03-28 17:25:31 +08:00
    已 star
    guanhui07
        8
    guanhui07  
       2022-03-28 18:08:30 +08:00
    ysmood
        9
    ysmood  
    OP
       2022-03-29 08:54:57 +08:00
    @guanhui07 goutil 的 dump 还是比较初级的,比如打印循环引用的数据它直接 crash , 而且打印的数据也过于冗杂,对于字符串里的回车等特殊字符也打印的有歧义,这不但不有助于 debug 反而容易隐藏 bug 。你可以试着用它来打印我示例里的数据就懂了。gop 打印的数据比 dump 少一个数量级。
    knowckx
        10
    knowckx  
       2022-03-30 10:29:19 +08:00
    哈哈这个我也想过,我有一个实用方案:

    func PrintJson(in interface{}) {
    res, err := json.MarshalIndent(in, "", "\t")
    if err != nil {
    fmt.Println("json marshal error", err)
    return
    }
    fmt.Println(string(res))
    }

    直接借用 json 序列化打印就行~方便快捷
    ysmood
        11
    ysmood  
    OP
       2022-03-30 10:36:22 +08:00
    @knowckx 这样无法打印私有变量,而且你用你这个方法打印我示例里的数据直接会 crash ,试试你就懂了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   972 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 18:56 · PVG 02:56 · LAX 10:56 · JFK 13:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.