定制软件开发Golang打印复杂结构体

fmt占位符

在Golang定制软件开发中有原生的 fmt 定制软件开发格式化工具去打印结构体,定制软件开发可以通过占位符%v、%+v、%#v去实现,这3定制软件开发种的区别如下所示:

  1. type User struct {
  2. Name string
  3. Age int
  4. }
  5. func main() {
  6. user := User{
  7. Name: "张三",
  8. Age: 95,
  9. }
  10. fmt.Printf("%v\", user)
  11. fmt.Printf("%+v\", user)
  12. fmt.Printf("%#v\", user)
  13. }

定制软件开发打印结果如下所示:

  1. {张三 95}
  2. {Name:张三 Age:95}
  3. main.User{Name:"张三", Age:95}

定制软件开发其中的区别:

  1. %v占位符是不会打印结构体字段名称的,字段之间以空格隔开;
  2. %+v占位符会打印字段名称,字段之间也是以空格隔开;
  3. %#v占位符则会打印结构体类型和字段名称,字段之间以逗号分隔

打印复杂结构体

当结构体中的字段是指针类型时,用占位符直接打印出来的是怎样的呢?

还是以前面的例子为基础,我们给“张三”加一条狗,其中 User 结构体中引入的 Dog 是指针类型,代码如下:

  1. type Dog struct {
  2. Name string
  3. Age int
  4. }
  5. type User struct {
  6. Name string
  7. Age int
  8. Dog *Dog
  9. }
  10. func main() {
  11. dog := Dog{
  12. Name: "旺财",
  13. Age: 2,
  14. }
  15. user := User{
  16. Name: "张三",
  17. Age: 95,
  18. Dog: &dog,
  19. }
  20. fmt.Println(user)
  21. fmt.Printf("%v\", user)
  22. fmt.Printf("%+v\", user)
  23. fmt.Printf("%#v\", user)
  24. }

这时还能把所有值打印出来吗?

  1. {张三 95 0xc000004078}
  2. {Name:张三 Age:95 Dog:0xc000004078}
  3. main.User{Name:"张三", Age:95, Dog:(*main.Dog)(0xc000004078)}

这时可以看到Dog字段打印的不是Dog结构体内部的值,而是一个地址值。很显然,这个不是我们需要在日志中看到的,我们需要看的是结构体具体的值,那这个值又怎么打印呢?

方案一:实现 String() 或GoString() 方法

Golang 中的 fmt 包中有一个 Stringer 接口,接口中只有一个 String() 方法

  1. // Stringer is implemented by any value that has a String method,
  2. // which defines the ``native'' format for that value.
  3. // The String method is used to print values passed as an operand
  4. // to any format that accepts a string or to an unformatted printer
  5. // such as Print.
  6. type Stringer interface {
  7. String() string
  8. }

我们可以让 User 和 Dog 结构体分别实现 String() 方法,这种方法类似于 Java 中的 toString() 方法。基于前面的代码,我们增加如下 String() 方法实现:

  1. func (d *Dog) String() string {
  2. return "{\"name" + "\": \"" + d.Name + "\"," + "\"" + "age\": \"" + strconv.Itoa(d.Age) + "\"}"
  3. }
  4. func (u *User) String() string {
  5. return "{\"name" + "\": \"" + u.Name + "\", \"" + "age\": \"" + strconv.Itoa(u.Age) + "\", \"dog\": " + u.Dog.String() + "}"
  6. }

运行后,打印的结果如下所示:

  1. {张三 95 {"name": "旺财","age": "2"}}
  2. {Name:张三 Age:95 Dog:{"name": "旺财","age": "2"}}
  3. main.User{Name:"张三", Age:95, Dog:(*main.Dog)(0xc000004078)}

发现,实现 String() 方法只对 %v 和 %+v 占位符有效,对于%#v 占位符,其打印的结构体指针类型还是一个地址值。

其实在 fmt 包中,Stringer 接口 下面,我们还可以看到另外一个 GoStringer 接口:

  1. // GoStringer is implemented by any value that has a GoString method,
  2. // which defines the Go syntax for that value.
  3. // The GoString method is used to print values passed as an operand
  4. // to a %#v format.
  5. type GoStringer interface {
  6. GoString() string
  7. }
The GoString method is used to print values passed as an operand to a %#v format. (GoString 方法用于打印作为操作数传递给 %#v 格式的值)

找到了,我们再实现 GoString() 方法,就可以用 %#v 占位符打印结构体指针类型中的值了。

基于之前代码增加如下代码:

  1. func (d *Dog) GoString() string {
  2. return "{\"name" + "\": \"" + d.Name + "\"," + "\"" + "age\": \"" + strconv.Itoa(d.Age) + "\"}"
  3. }
  4. func (u *User) GoString() string {
  5. return "{\"name" + "\": \"" + u.Name + "\", \"" + "age\": \"" + strconv.Itoa(u.Age) + "\", \"dog\": " + u.Dog.String() + "}"
  6. }

 运行后,打印结果如下所示,这下子就都可以打印了:

  1. {张三 95 {"name": "旺财","age": "2"}}
  2. {Name:张三 Age:95 Dog:{"name": "旺财","age": "2"}}
  3. main.User{Name:"张三", Age:95, Dog:{"name": "旺财","age": "2"}}

到这里,我感觉这种方案有点麻烦呢,还有没有其他不用维护 String() 或 GoString() 的方法呢?

方案二:转换成 json 格式

  1. func main() {
  2. dog := Dog{
  3. Name: "旺财",
  4. Age: 2,
  5. }
  6. user := User{
  7. Name: "张三",
  8. Age: 95,
  9. Dog: &dog,
  10. }
  11. byteUser, _ := json.Marshal(&user)
  12. fmt.Println(string(byteUser))
  13. }

打印结果如下所示,如果使用 json 库的话,是可以直接把结构体指针类型的具体值都打印出来的,比较方便:

{"Name":"张三","Age":95,"Dog":{"Name":"旺财","Age":2}}

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发