golang之帶指針的結構體格式化打印


 

https://www.jianshu.com/p/1b04d75769a7

Golang里的格式化字符額外提供了%v%+v%#v,可以用作打印一些基礎類型的值,同時也支持打印接口和結構體。

func main() { num := 1 str := "ted" sleep := false fmt.Printf("num: %v, str: %v, sleep: %v\n", num, str, sleep) stu := student{ id: 0, name: "ted", } var numInterface interface{} numInterface=num fmt.Printf("stu: %v, numInterface: %v\n", stu, numInterface) fmt.Printf("stu: %+v, numInterface: %+v\n", stu, numInterface) fmt.Printf("stu: %#v, numInterface: %#v\n", stu, numInterface) } 

上述代碼的執行結果如下:

num: 1, str: ted, sleep: false stu: {0 ted}, numInterface: 1 stu: {id:0 name:ted}, numInterface: 1 stu: main.student{id:0, name:"ted"}, numInterface: 1 
  • %v在打印接口類型時,會打印出其實際的值。而在打印結構體對象時,打印的是結構體成員對象的值。
  • %+v打印結構體對象中的字段類型+字段值。
  • %#v先打印結構體名,再輸出結構體對象的字段類型+字段的值。

同理當結構體中存在指針成員時,打印的指針成員的值是指針本身的值,而不是指針指向的值,參考如下代碼:

package main import "fmt" type student struct { id int32 name *string } func main() { name := "gxt" stu := student{id: 1, name: &name} fmt.Printf("stu: %v\n", stu) fmt.Printf("stu: %+v\n", stu) fmt.Printf("stu: %#v\n", stu) } 

輸出結果:

stu: {1 0xc000010240} stu: {id:1 name:0xc000010240} stu: main.student{id:1, name:(*string)(0xc000010240)} 

實際上Golang的fmt包中已經提供了Stringers接口用於自定義某種類型的字符串打印信息。

// 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 } 

因此只需要給上述代碼中的student結構體實現該接口即可。參考代碼如下:


package main import "fmt" type student struct { id int32 name *string } func (s student) String() string { return fmt.Sprintf("{id: %v, name: %v}", s.id, *s.name) } func main() { name := "ted" stu := student{id: 1, name: &name} fmt.Printf("stu: %v\n", stu) fmt.Printf("stu: %+v\n", stu) fmt.Printf("stu: %#v\n", stu) } 

結果如下:

stu: {id: 1, name: ted} stu: {id: 1, name: ted} stu: main.student{id:1, name:(*string)(0xc000010240)} 

可以看到即使重寫了String()方法后,對%#v仍不起作用,在平時編程中要注意這一點。

進一步考慮如果結構體中嵌套了其他結構體對象指針,這種情況需要怎么處理呢?參考如下代碼:

package main import ( "encoding/json" "fmt" ) type studentP struct { id int32 name *string score *score } type score struct { math *int english int } func (s *studentP) String() string { return fmt.Sprintf("{id: %v, name: %v, score: %v}", s.id, *s.name, s.score) } func (s *score) String() string { return fmt.Sprintf("{math:%v, english:%v}", *s.math, s.english) } func main() { name := "gxt" math := 99 stu := &studentP{ id: 0, name: &name, score: &score{ math: &math, english: 100, }, } fmt.Printf("std: %v\n",stu) } 

結果如下:

std: {id: 0, name: gxt, score: {math:99, english:100}} 

上述代碼中,即使是嵌套了指針類型的結構體對象,只要子結構體對象也實現了String()方法,也可以正常通過%v%+v打印出結構體的各個成員內容。整體機制比較類似於Java語言中的toString()方法。

注意:在實現String()方法時,需要注意receiver是對象還是指針,關系到打印嵌套式結構體對象時的傳參。



作者:LandscapeTed
鏈接:https://www.jianshu.com/p/1b04d75769a7
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM