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

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

介绍

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

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

type Stringer interface {
    String() string
}

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

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

打印指针类型的值

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

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

输出结果:

{1 0xc000096210}

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

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

func (u User) String() string {
 return fmt.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 {
 return fmt.Sprintf("{Id: %v, Name: %v}", u.Id, *u.Name)
}

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

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

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

04

总结

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

推荐阅读:


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
2月前
|
C语言
指向结构体数组的指针
指向结构体数组的指针
15 2
|
4天前
|
Go 开发者
Golang深入浅出之-Go语言上下文(context)包:处理取消与超时
【4月更文挑战第23天】Go语言的`context`包提供`Context`接口用于处理任务取消、超时和截止日期。通过传递`Context`对象,开发者能轻松实现复杂控制流。本文解析`context`包特性,讨论常见问题和解决方案,并给出代码示例。关键点包括:1) 确保将`Context`传递给所有相关任务;2) 根据需求选择适当的`Context`创建函数;3) 定期检查`Done()`通道以响应取消请求。正确使用`context`包能提升Go程序的控制流管理效率。
14 1
|
5天前
|
安全 Go 开发者
Golang深入浅出之-Go语言并发编程面试:Goroutine简介与创建
【4月更文挑战第22天】Go语言的Goroutine是其并发模型的核心,是一种轻量级线程,能低成本创建和销毁,支持并发和并行执行。创建Goroutine使用`go`关键字,如`go sayHello("Alice")`。常见问题包括忘记使用`go`关键字、不正确处理通道同步和关闭、以及Goroutine泄漏。解决方法包括确保使用`go`启动函数、在发送完数据后关闭通道、设置Goroutine退出条件。理解并掌握这些能帮助开发者编写高效、安全的并发程序。
13 1
|
5天前
|
JSON 编译器 Go
Golang深入浅出之-结构体标签(Tags):JSON序列化与反射应用
【4月更文挑战第22天】Go语言结构体标签用于添加元信息,常用于JSON序列化和ORM框架。本文聚焦JSON序列化和反射应用,讨论了如何使用`json`标签处理敏感字段、实现`omitempty`、自定义字段名和嵌套结构体。同时,通过反射访问标签信息,但应注意反射可能带来的性能问题。正确使用结构体标签能提升代码质量和安全性。
9 0
|
5天前
|
Go 开发者
Golang深入浅出之-Go语言结构体(struct)入门:定义与使用
【4月更文挑战第22天】Go语言中的结构体是构建复杂数据类型的关键,允许组合多种字段。本文探讨了结构体定义、使用及常见问题。结构体定义如`type Person struct { Name string; Age int; Address Address }`。问题包括未初始化字段的默认值、比较含不可比较字段的结构体以及嵌入结构体字段重名。避免方法包括初始化结构体、自定义比较逻辑和使用明确字段选择器。结构体方法、指针接收者和匿名字段嵌入提供了灵活性。理解这些问题和解决策略能提升Go语言编程的效率和代码质量。
21 1
|
5天前
|
SQL 关系型数据库 MySQL
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
|
6天前
|
Go 开发者
Golang深入浅出之-Go语言流程控制:if、switch、for循环详解
【4月更文挑战第21天】本文介绍了Go语言中的流程控制语句,包括`if`、`switch`和`for`循环。`if`语句支持简洁的语法和初始化语句,但需注意比较运算符的使用。`switch`语句提供多分支匹配,可省略`break`,同时支持不带表达式的形式。`for`循环有多种形式,如基本循环和`for-range`遍历,遍历时修改原集合可能导致未定义行为。理解并避免易错点能提高代码质量和稳定性。通过实践代码示例,可以更好地掌握Go语言的流程控制。
12 3
Golang深入浅出之-Go语言流程控制:if、switch、for循环详解
|
6天前
|
Go
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
【4月更文挑战第21天】Go语言函数是代码组织的基本单元,用于封装可重用逻辑。本文介绍了函数定义(包括基本形式、命名、参数列表和多返回值)、调用以及匿名函数与闭包。在函数定义时,注意参数命名和注释,避免参数顺序混淆。在调用时,要检查并处理多返回值中的错误。理解闭包原理,小心处理外部变量引用,以提升代码质量和可维护性。通过实践和示例,能更好地掌握Go语言函数。
20 1
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
|
7天前
|
Go
Golang深入浅出之-Go语言基础语法:变量声明与赋值
【4月更文挑战第20天】本文介绍了Go语言中变量声明与赋值的基础知识,包括使用`var`关键字和简短声明`:=`的方式,以及多变量声明与赋值。强调了变量作用域、遮蔽、初始化与零值的重要性,并提醒读者注意类型推断时的一致性。了解这些概念有助于避免常见错误,提高编程技能和面试表现。
21 0
|
7天前
|
安全 Java Linux
Golang深入浅出之-初识Go语言:语言特点与开发环境搭建
【4月更文挑战第20天】Go语言(Golang)由Google于2009年推出,以其简洁语法、高效执行、强大的并发模型和丰富标准库著称。主要特点包括:1) 代码结构清晰,易于阅读;2) 编译速度快,运行效率高,内置垃圾回收;3) 使用goroutines和channels实现并发;4) 标准库涵盖网络、并发等多个领域;5) 支持跨平台编译。要搭建开发环境,需下载Go SDK,配置环境变量,并验证安装。常见问题涉及导入包未使用、错误处理、并发安全和`defer`语句的使用。
16 0