Golang Go语言中日志如何打印带指针的结构体

发布于 1周前 作者 sinazl 来自 Go语言
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 里面打印这种日志大家有什么好方法吗?


Golang Go语言中日志如何打印带指针的结构体

更多关于Golang Go语言中日志如何打印带指针的结构体的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

15 回复

转成 json

更多关于Golang Go语言中日志如何打印带指针的结构体的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


请问大佬现在公司里是这么用的吗?感觉转成 json 又要处理一次 error ,然后使用哪个 json 包又可能涉及性能问题,毕竟打印日志是很频繁的操作

十分感谢,这种自己用着很方便。公司的项目不太敢用,看这个好像也是用了反射,怕有性能影响。

其实正常来说是不允许打印结构体的,因为里面会包含用户隐私信息,这样做会有信息安全风险。

现成的那么多 log 库你不用,偏要自己打。
https://zhuanlan.zhihu.com/p/431434480

zap.Any 就很爽

感谢各位大佬

说实在的 go 的 log 库没设计成 interface 真是标准库的最大败笔

很少有需要 log 整个 struct 的情况吧,go 的设计了就是要为每个对象实现 String 方法, 这也是比 Printf 高效得多的方法

如果只是调试大于 fmt.Printf("%+v", teacher)

最近 Go 有一个在标准库中添加结构化日志的讨论,有兴趣可以关注下 https://github.com/golang/go/discussions/54763

gop 一般不会有全隐患,这个库是设计给单元测试用的,你如果用在了其他的文件里,而你又用了 error 返回 lint 检测的话就回报错,这是 gop 故意设计成这样的,防止你在 production 环境里使用它。

zap 感觉靠谱。我用一下

在Go语言中,直接打印带指针的结构体(即指向结构体的指针)时,通常会显示内存地址而不是结构体的内容。为了打印结构体指针指向的内容,可以使用以下几种方法:

  1. 使用 * 运算符解引用指针: 在 fmt.Printlnfmt.Printf 中,可以通过 * 运算符解引用指针,从而打印指针指向的实际结构体内容。例如:

    type Person struct {
        Name string
        Age  int
    }
    
    p := &Person{Name: "Alice", Age: 30}
    fmt.Printf("%+v\n", *p)  // %+v 会打印结构体的字段名和值
    
  2. 使用 reflect: 如果需要更复杂的打印逻辑或自定义格式,可以使用 reflect 包。reflect.ValueOf(p).Elem() 可以获取指针指向的值,然后进一步处理。

  3. 自定义方法: 为结构体类型定义一个 String() 方法,这样在任何需要字符串表示的地方(如 fmt.Println)都会自动调用该方法。例如:

    func (p *Person) String() string {
        return fmt.Sprintf("Person{Name: %s, Age: %d}", p.Name, p.Age)
    }
    
    p := &Person{Name: "Alice", Age: 30}
    fmt.Println(p)  // 会调用 p 的 String() 方法
    

选择哪种方法取决于具体需求,对于简单的打印,解引用指针是最直接和常用的方式。

回到顶部