Golang 語言怎么打印結(jié)構(gòu)體指針類型字段的值?
01介紹
在 Golang 語言開發(fā)中,我們經(jīng)常會(huì)使用結(jié)構(gòu)體類型,如果我們使用的結(jié)構(gòu)體類型的變量包含指針類型的字段,我們在記錄日志的時(shí)候,指針類型的字段的值是指針地址,將會(huì)給我們 debug 代碼造成不便。
實(shí)際上,Golang 為我們提供了一個(gè)接口類型 Stringer ,它是一個(gè)支持以字符串形式描述自己的類型,它只提供了一個(gè)方法,應(yīng)該是 Golang 中最簡單和最常用的接口之一,它由 fmt 包定義。
- type Stringer interface {
 - String() string
 - }
 
fmt 包的打印函數(shù)會(huì)檢查你的類型是否實(shí)現(xiàn)該接口,以便知道怎么打印你的變量。所以,我們在記錄日志的時(shí)候,如果需要記錄的變量是具有指針類型字段的結(jié)構(gòu)體,我們不妨也為該結(jié)構(gòu)體類型定義 String 方法,用來實(shí)現(xiàn)可以記錄指針字段的實(shí)際值的目的。
本文我們介紹怎么通過實(shí)現(xiàn) Stringer 接口,讓我們的代碼更優(yōu)雅。
02打印指針類型的值
讀者朋友們在 Golang 程序開發(fā)中,一定也會(huì)使用到包含指針類型字段的結(jié)構(gòu)體,你是否在記錄日志的時(shí)候,發(fā)現(xiàn)記錄的值是指針地址,給你 debug 代碼造成不便呢?
- func main() {
 - name := "frank"
 - user := User{
 - Id: 1,
 - Name: &name,
 - }
 - fmt.Println(user)
 - }
 - type User struct {
 - Id int
 - Name *string
 - }
 
輸出結(jié)果:
- {1 0xc000096210}
 
閱讀上面這段代碼,我們構(gòu)造了一個(gè)包含指針類型字段的結(jié)構(gòu)體,然后打印該結(jié)構(gòu)體類型的變量,輸出結(jié)果中指針類型的字段 Name 的值是指針地址,而不是我們想要的字段值 frank。
試想一下,如果我們記錄的日志中,變量的值是指針地址,將會(huì)對我們 debug 代碼造成不變,所以我們需要使用 Golang 提供的接口 Stringer 解決該問題。
- func (u User) String() string {
 - return fmt.Sprintf("{Id: %v, Name: %v}", u.Id, *u.Name)
 - }
 
輸出結(jié)果:
- {Id: 1, Name: frank}
 
閱讀上面這段代碼,我們給類型 User 定義了 String 方法,通過實(shí)現(xiàn) Golang 的 Stringer 接口,來實(shí)現(xiàn)打印指針類型變量的實(shí)際值的目的。
03避“坑”
讀者朋友們閱讀完以上內(nèi)容,應(yīng)該已經(jīng)學(xué)會(huì)了怎么使用接口 Stringer 實(shí)現(xiàn)打印指針類型變量的值。不過,我還是想列舉一個(gè)異常情況,幫助 Golang 新手讀者朋友避“坑”。如果你已經(jīng)是 Golang 老手,本節(jié)內(nèi)容可以跳過。
- func (u *User) String() string {
 - return fmt.Sprintf("{Id: %v, Name: %v}", u.Id, *u.Name)
 - }
 
閱讀上面這段代碼,我們將類型方法的接收者改為指針類型,我相信大多數(shù)讀者朋友們會(huì)使用指針類型的接收者。此時(shí),讀者朋友會(huì)發(fā)現(xiàn)輸出結(jié)果沒有使用我們定義的 String 方法,而是輸出的指針類型字段的指針地址。
想要解決這個(gè)問題也很簡單,我們只需要在定義結(jié)構(gòu)體類型變量的時(shí)候,使用指針類型,這樣 fmt 包的打印函數(shù)就可以自動(dòng)執(zhí)行我們定義的 String 方法了。
- func main() {
 - name := "frank"
 - user := &User{
 - Id: 1,
 - Name: &name,
 - }
 - fmt.Println(user)
 - }
 
04總結(jié)
本文我們介紹了怎么打印包含指針類型變量的結(jié)構(gòu)體類型變量的值,在我們需要記錄日志的時(shí)候,不用再因?yàn)橛涗浀氖侵羔樀刂罚瑥亩o我們 debug 代碼造成不便。
參考資料:
https://go.dev/doc/effective_go#pointers_vs_values
https://go.dev/tour/methods/17
















 
 
 









 
 
 
 