網站首頁 編程語言 正文
fmt結構體占位符
在Golang中有原生的 fmt 格式化工具去打印結構體,可以通過占位符%v、%+v、%#v去實現,這3種的區別如下所示:
type User struct { Name string Age int } func main() { user := User{ Name: "張三", Age: 95, } fmt.Printf("%v\n", user) fmt.Printf("%+v\n", user) fmt.Printf("%#v\n", user) }
打印結果如下所示:
{張三 95} ? ? ? ? ? ? ? ? ? ??
{Name:張三 Age:95} ? ? ? ? ? ?
main.User{Name:"張三", Age:95}
其中的區別:
- %v占位符是不會打印結構體字段名稱的,字段之間以空格隔開;
- %+v占位符會打印字段名稱,字段之間也是以空格隔開;
- %#v占位符則會打印結構體類型和字段名稱,字段之間以逗號分隔
打印復雜結構體
當結構體中的字段是指針類型時,用占位符直接打印出來的是怎樣的呢?
還是以前面的例子為基礎,我們給“張三”加一條狗,其中 User 結構體中引入的 Dog 是指針類型,代碼如下:
type Dog struct { Name string Age int } type User struct { Name string Age int Dog *Dog } func main() { dog := Dog{ Name: "旺財", Age: 2, } user := User{ Name: "張三", Age: 95, Dog: &dog, } fmt.Println(user) fmt.Printf("%v\n", user) fmt.Printf("%+v\n", user) fmt.Printf("%#v\n", user) }
這時還能把所有值打印出來嗎?
{張三 95 0xc000004078} ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
{Name:張三 Age:95 Dog:0xc000004078} ? ? ? ? ? ? ? ? ? ? ? ? ?
main.User{Name:"張三", Age:95, Dog:(*main.Dog)(0xc000004078)}
這時可以看到Dog字段打印的不是Dog結構體內部的值,而是一個地址值。很顯然,這個不是我們需要在日志中看到的,我們需要看的是結構體具體的值,那這個值又怎么打印呢?
方案一
實現 String() 或GoString() 方法
Golang 中的 fmt 包中有一個 Stringer 接口,接口中只有一個 String() 方法
// Stringer is implemented by any value that has a String method, // which defines the ``native'' format for that value. // The String method is used to print values passed as an operand // to any format that accepts a string or to an unformatted printer // such as Print. type Stringer interface { String() string }
我們可以讓 User 和 Dog 結構體分別實現 String() 方法,這種方法類似于 Java 中的 toString() 方法。基于前面的代碼,我們增加如下 String() 方法實現:
func (d *Dog) String() string { return "{\"name" + "\": \"" + d.Name + "\"," + "\"" + "age\": \"" + strconv.Itoa(d.Age) + "\"}" } func (u *User) String() string { return "{\"name" + "\": \"" + u.Name + "\", \"" + "age\": \"" + strconv.Itoa(u.Age) + "\", \"dog\": " + u.Dog.String() + "}" }
運行后,打印的結果如下所示:
{張三 95 {"name": "旺財","age": "2"}} ? ? ? ? ? ? ? ? ? ? ? ?
{Name:張三 Age:95 Dog:{"name": "旺財","age": "2"}} ? ? ? ? ??
main.User{Name:"張三", Age:95, Dog:(*main.Dog)(0xc000004078)}
發現,實現 String() 方法只對 %v 和 %+v 占位符有效,對于%#v 占位符,其打印的結構體指針類型還是一個地址值。
其實在 fmt 包中,Stringer 接口 下面,我們還可以看到另外一個 GoStringer 接口:
// GoStringer is implemented by any value that has a GoString method, // which defines the Go syntax for that value. // The GoString method is used to print values passed as an operand // to a %#v format. type GoStringer interface { GoString() string }
The GoString method is used to print values passed as an operand to a %#v format. (GoString 方法用于打印作為操作數傳遞給 %#v 格式的值)
找到了,我們再實現 GoString() 方法,就可以用 %#v 占位符打印結構體指針類型中的值了。
基于之前代碼增加如下代碼:
func (d *Dog) GoString() string { return "{\"name" + "\": \"" + d.Name + "\"," + "\"" + "age\": \"" + strconv.Itoa(d.Age) + "\"}" } func (u *User) GoString() string { return "{\"name" + "\": \"" + u.Name + "\", \"" + "age\": \"" + strconv.Itoa(u.Age) + "\", \"dog\": " + u.Dog.String() + "}" }
運行后,打印結果如下所示,這下子就都可以打印了:
{張三 95 {"name": "旺財","age": "2"}} ? ? ? ? ? ? ? ? ? ? ? ? ?
{Name:張三 Age:95 Dog:{"name": "旺財","age": "2"}} ? ? ? ? ? ??
main.User{Name:"張三", Age:95, Dog:{"name": "旺財","age": "2"}}
到這里,我感覺這種方案有點麻煩呢,還有沒有其他不用維護 String() 或 GoString() 的方法呢?
方案二
轉換成 json 格式
func main() { dog := Dog{ Name: "旺財", Age: 2, } user := User{ Name: "張三", Age: 95, Dog: &dog, } byteUser, _ := json.Marshal(&user) fmt.Println(string(byteUser)) }
打印結果如下所示,如果使用 json 庫的話,是可以直接把結構體指針類型的具體值都打印出來的,比較方便:
{"Name":"張三","Age":95,"Dog":{"Name":"旺財","Age":2}}
原文鏈接:https://blog.csdn.net/weixin_38418951/article/details/122904621
相關推薦
- 2023-03-20 C#字符集編碼的使用及說明_C#教程
- 2022-06-28 C語言簡明清晰講解枚舉_C 語言
- 2023-08-13 git版本管理常用命令
- 2022-04-17 Bootstrap typeahead自動補全插件的坑
- 2024-01-31 nginx配置文件中最后一個 include servers/*;作用是什么?
- 2023-03-16 python中asyncore異步模塊的實現_python
- 2022-09-09 PyTorch策略梯度算法詳情_python
- 2023-04-29 C/C++并查集的查詢與合并實現原理_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支