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

golang 日志如何打印带指针的结构体

  •  
  •   trivisa · 2022-09-03 13:25:41 +08:00 · 3263 次点击
    这是一个创建于 830 天前的主题,其中的信息可能已经有所发展或是发生改变。
    package main
    import (
    	"fmt"
    )
    type Student struct{
    	StudentName *string
    }
    type Teacher struct {
    	TeacherName *string
    	Student1 Student
    	Student2 *Student
    }
    
    func main() {    
    	studentName := "zhangsan"
    	teacherName := "teacher"
    	student := Student{
    		StudentName:&studentName,
    	}	
    	teacher := Teacher {
    		TeacherName : &teacherName,
    		Student1: student,
    		Student2: &student,
    	}
    	fmt.Printf("%v\n",teacher)	
    }
    

    如上述代码会打印如下输出 {0xc0000a0220 {0xc0000a0210} 0xc0000b6018},这种东西打到日志里面一点用都没有,然后测试同学来问我这里是不是加密了,搞得我很尴尬

    查询到网上的方法是,为指针添加 String 方法,如

    func (s *Student) String() string{
    	return fmt.Sprintf("{[CustomStudent]name:%s}",*s.StudentName)
    }
    

    但是仍然输出存在问题 {0xc000096220 {0xc000096210} {[CustomStudent]name:zhangsan}}

    改为为结构体本身添加 String 方法 ok

    func (s Student) String() string{
    	return fmt.Sprintf("{[CustomStudent]name:%s}",*s.StudentName)
    }
    

    输出 {0xc000010260 {[CustomStudent]name:zhangsan} {[CustomStudent]name:zhangsan}}

    但是很明显,要为每个结构体手动添加 String 方法还是比较繁琐且枯燥的。而且我也不想改项目组里以前的代码,虽然加个 String 方法没啥太大风险。

    之前做 java 虽然也是每个类都有 string 方法,但好歹是可以自动生成的,golang 里面打印这种日志大家有什么好方法吗?

    14 条回复    2022-09-07 10:33:24 +08:00
    danbai
        1
    danbai  
       2022-09-03 13:38:37 +08:00 via Android
    转成 json
    iyaozhen
        2
    iyaozhen  
       2022-09-03 13:40:40 +08:00   ❤️ 1
    https://www.v2ex.com/t/842121 推荐个大佬写的
    trivisa
        3
    trivisa  
    OP
       2022-09-03 13:43:12 +08:00
    @danbai 请问大佬现在公司里是这么用的吗?感觉转成 json 又要处理一次 error ,然后使用哪个 json 包又可能涉及性能问题,毕竟打印日志是很频繁的操作
    trivisa
        4
    trivisa  
    OP
       2022-09-03 13:46:13 +08:00
    @iyaozhen 十分感谢,这种自己用着很方便。公司的项目不太敢用,看这个好像也是用了反射,怕有性能影响。
    iyaozhen
        5
    iyaozhen  
       2022-09-03 13:47:04 +08:00
    @trivisa 其实正常来说是不允许打印结构体的,因为里面会包含用户隐私信息,这样做会有信息安全风险。
    lasuar
        6
    lasuar  
       2022-09-03 13:48:16 +08:00
    现成的那么多 log 库你不用,偏要自己打。
    https://zhuanlan.zhihu.com/p/431434480
    ryalu
        7
    ryalu  
       2022-09-03 15:33:07 +08:00
    foam
        8
    foam  
       2022-09-03 15:46:01 +08:00
    zap.Any 就很爽
    trivisa
        9
    trivisa  
    OP
       2022-09-03 17:18:43 +08:00
    感谢各位大佬
    ptyfork
        10
    ptyfork  
       2022-09-03 20:44:55 +08:00
    说实在的 go 的 log 库没设计成 interface 真是标准库的最大败笔
    lysS
        11
    lysS  
       2022-09-04 10:30:51 +08:00
    很少有需要 log 整个 struct 的情况吧,go 的设计了就是要为每个对象实现 String 方法, 这也是比 Printf 高效得多的方法

    如果只是调试大于 fmt.Printf("%+v", teacher)
    mengyx
        12
    mengyx  
       2022-09-04 14:04:58 +08:00 via Android
    最近 Go 有一个在标准库中添加结构化日志的讨论,有兴趣可以关注下 https://github.com/golang/go/discussions/54763
    ysmood
        13
    ysmood  
       2022-09-05 08:12:40 +08:00 via Android   ❤️ 1
    @iyaozhen gop 一般不会有全隐患,这个库是设计给单元测试用的,你如果用在了其他的文件里,而你又用了 error 返回 lint 检测的话就回报错,这是 gop 故意设计成这样的,防止你在 production 环境里使用它。
    runningman
        14
    runningman  
       2022-09-07 10:33:24 +08:00
    zap 感觉靠谱。我用一下
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4979 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 09:12 · PVG 17:12 · LAX 01:12 · JFK 04:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.