深圳幻海软件技术有限公司 欢迎您!

Golang 语言怎么打印结构体指针类型字段的值?

2023-02-28

01介绍在Golang语言开发中,我们经常会使用结构体类型,如果我们使用的结构体类型的变量包含指针类型的字段,我们在记录日志的时候,指针类型的字段的值是指针地址,将会给我们debug代码造成不便。实际上,Golang为我们提供了一个接口类型Stringer,它是一个支持以字符串形式描述自己的类型,它

01介绍

在 Golang 语言开发中,我们经常会使用结构体类型,如果我们使用的结构体类型的变量包含指针类型的字段,我们在记录日志的时候,指针类型的字段的值是指针地址,将会给我们 debug 代码造成不便。

实际上,Golang 为我们提供了一个接口类型 Stringer ,它是一个支持以字符串形式描述自己的类型,它只提供了一个方法,应该是 Golang 中最简单和最常用的接口之一,它由 fmt 包定义。

type Stringer interface { 
    String() string 

  • 1.
  • 2.
  • 3.

fmt 包的打印函数会检查你的类型是否实现该接口,以便知道怎么打印你的变量。所以,我们在记录日志的时候,如果需要记录的变量是具有指针类型字段的结构体,我们不妨也为该结构体类型定义 String 方法,用来实现可以记录指针字段的实际值的目的。

本文我们介绍怎么通过实现 Stringer 接口,让我们的代码更优雅。

02打印指针类型的值

读者朋友们在 Golang 程序开发中,一定也会使用到包含指针类型字段的结构体,你是否在记录日志的时候,发现记录的值是指针地址,给你 debug 代码造成不便呢?

func main() { 
 name := "frank" 
 user := User
  Id:   1, 
  Name: &name
 } 
 fmt.Println(user

 
type User struct { 
 Id   int 
 Name *string 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

输出结果:

{1 0xc000096210} 
  • 1.

阅读上面这段代码,我们构造了一个包含指针类型字段的结构体,然后打印该结构体类型的变量,输出结果中指针类型的字段 Name 的值是指针地址,而不是我们想要的字段值 frank。

试想一下,如果我们记录的日志中,变量的值是指针地址,将会对我们 debug 代码造成不变,所以我们需要使用 Golang 提供的接口 Stringer 解决该问题。

func (u User) String() string { 
 return fmt.Sprintf("{Id: %v, Name: %v}", u.Id, *u.Name

  • 1.
  • 2.
  • 3.

输出结果:

{Id: 1, Name: frank} 
  • 1.

阅读上面这段代码,我们给类型 User 定义了 String 方法,通过实现 Golang 的 Stringer 接口,来实现打印指针类型变量的实际值的目的。

03避“坑”

读者朋友们阅读完以上内容,应该已经学会了怎么使用接口 Stringer 实现打印指针类型变量的值。不过,我还是想列举一个异常情况,帮助 Golang 新手读者朋友避“坑”。如果你已经是 Golang 老手,本节内容可以跳过。

func (u *User) String() string { 
 return fmt.Sprintf("{Id: %v, Name: %v}", u.Id, *u.Name

  • 1.
  • 2.
  • 3.

阅读上面这段代码,我们将类型方法的接收者改为指针类型,我相信大多数读者朋友们会使用指针类型的接收者。此时,读者朋友会发现输出结果没有使用我们定义的 String 方法,而是输出的指针类型字段的指针地址。

想要解决这个问题也很简单,我们只需要在定义结构体类型变量的时候,使用指针类型,这样 fmt 包的打印函数就可以自动执行我们定义的 String 方法了。

func main() { 
 name := "frank" 
 user := &User
  Id:   1, 
  Name: &name
 } 
 fmt.Println(user

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

04总结

本文我们介绍了怎么打印包含指针类型变量的结构体类型变量的值,在我们需要记录日志的时候,不用再因为记录的是指针地址,从而给我们 debug 代码造成不便。

参考资料:

https://go.dev/doc/effective_go#pointers_vs_values

 

https://go.dev/tour/methods/17