01介绍在Golang语言开发中,我们经常会用到结构类型。如果我们使用的结构体类型变量中包含指针类型字段,那么在记录日志时,指针类型字段的值为指针地址,会给我们的调试代码带来不便。实际上,Golang为我们提供了一个接口类型Stringer,它是一个支持以字符串形式描述自身的类型。它只提供了一个方法,应该是Golang中最简单最常用的接口之一。它由fmt包定义组成。typeStringerinterface{String()string}fmt包的打印函数会检查您的类型是否实现了此接口,以便它知道如何打印您的变量。因此,我们在记录日志的时候,如果要记录的变量是一个指针类型字段的结构体,我们不妨为该结构体类型定义一个String方法,以达到记录指针字段实际值的目的。在本文中,我们将介绍如何通过实现Stringer接口使我们的代码更加优雅。02打印指针类型的值。读者朋友在Golang程序开发中肯定会用到包含指针类型字段的结构体。当你记录日志的时候,你发现记录的值是指针地址,这会给你的调试代码带来不便。funcmain(){name:="frank"user:=User{Id:1,Name:&name,}fmt.Println(user)}typeUserstruct{IdintName*string}Output:{10xc000096210}看了上面的代码,我们构造一个包含指针类型字段的结构体,然后打印该结构体类型的变量,输出结果中指针类型字段Name的值为指针地址,并不是我们想要的字段值frank。试想一下,如果我们记录的日志中变量的值是一个指针地址,并不会改变我们的调试代码,那么我们就需要使用Golang提供的接口Stringer来解决这个问题。func(uUser)String()string{returnfmt.Sprintf("{Id:%v,Name:%v}",u.Id,*u.Name)}输出结果:{Id:1,Name:frank}读取在上面的代码中,我们为User类型定义了String方法,通过实现Golang的Stringer接口来实现打印指针类型变量实际值的目的。03避免“陷阱”读者朋友看了以上内容,应该已经学会了如何使用Stringer接口打印指针类型变量的值。不过,我还是想列举一个异常情况,帮助Golang新手读者避免“坑”。如果你已经是Golang老手,可以跳过这一部分。func(u*User)String()string{returnfmt.Sprintf("{Id:%v,Name:%v}",u.Id,*u.Name)}阅读上面的代码,我们将类型方法接收者更改为指针类型。相信大多数读者都会使用指针类型的接收器。至此,读者会发现输出结果并没有使用我们定义的String方法,而是输出指针类型字段的指针地址。解决这个问题也很简单。我们只需要在定义结构体类型变量的时候使用指针类型,这样fmt包的print函数就可以自动执行我们定义的String方法。funcmain(){name:="frank"user:=&User{Id:1,Name:&name,}fmt.Println(user)}04总结在这篇文章中,我们介绍了如何打印一个结构类型变量的值,其中包含一个指针类型的变量,当我们需要记录日志的时候,就不需要再因为记录了指针地址而给我们的调试代码带来不便。参考资料:https://go.dev/doc/effective_go#pointers_vs_valueshttps://go.dev/tour/methods/17
