【问题标题】:如何在控制台中打印结构变量?
【发布时间】:2014-08-22 02:56:19
【问题描述】:

如何在 Golang 中打印(在控制台中)此结构的 IdTitleName 等?

type Project struct {
    Id      int64   `json:"project_id"`
    Title   string  `json:"title"`
    Name    string  `json:"name"`
    Data    Data    `json:"data"`
    Commits Commits `json:"commits"`
}

【问题讨论】:

标签: struct go


【解决方案1】:
推荐的答案 Go Language

打印结构中字段的名称:

fmt.Printf("%+v\n", yourProject)

来自fmt package

打印结构时,加号标志 (%+v) 添加字段名称

假设您有一个 Project 实例(在 'yourProject' 中)

文章JSON and Go 将详细介绍如何从 JSON 结构中检索值。


Go by example page 提供了另一种技术:

type Response2 struct {
  Page   int      `json:"page"`
  Fruits []string `json:"fruits"`
}

res2D := &Response2{
    Page:   1,
    Fruits: []string{"apple", "peach", "pear"}}
res2B, _ := json.Marshal(res2D)
fmt.Println(string(res2B))

那会打印出来:

{"page":1,"fruits":["apple","peach","pear"]}

如果您没有任何实例,则需要 use reflection 显示给定结构的字段名称,as in this example

type T struct {
    A int
    B string
}

t := T{23, "skidoo"}
s := reflect.ValueOf(&t).Elem()
typeOfT := s.Type()

for i := 0; i < s.NumField(); i++ {
    f := s.Field(i)
    fmt.Printf("%d: %s %s = %v\n", i,
        typeOfT.Field(i).Name, f.Type(), f.Interface())
}

【讨论】:

  • 感谢您的回答,但还有一件事。我的 JSON 文件与 API 相关......因此我不想设置 ID 或名称,我只想通过 API 获取它并在控制台中打印它。我该怎么做?
  • @fnr 如果你有一个 JSON 文档,你需要解组它,然后才能打印它的字段。
  • 点赞!我的一个抱怨是 %+v 命令不能很好地打印它!我仍然对这条生产线的效率感到满意。
  • 需要为json编组技术导入“encoding/json”,
  • 请注意,.Printf("%+v\n") 也适用于“log”包
【解决方案2】:

我想推荐go-spew,根据他们的 github “为 Go 数据结构实现了一个深度漂亮的打印机以帮助调试”

go get -u github.com/davecgh/go-spew/spew

用法示例:

package main

import (
    "github.com/davecgh/go-spew/spew"
)

type Project struct {
    Id      int64  `json:"project_id"`
    Title   string `json:"title"`
    Name    string `json:"name"`
    Data    string `json:"data"`
    Commits string `json:"commits"`
}

func main() {

    o := Project{Name: "hello", Title: "world"}
    spew.Dump(o)
}

输出:

(main.Project) {
 Id: (int64) 0,
 Title: (string) (len=5) "world",
 Name: (string) (len=5) "hello",
 Data: (string) "",
 Commits: (string) ""
}

【讨论】:

  • 您可以添加 go-spew 的取消引用功能。它允许您打印指针引用的结构的值,而不是指针 itel
  • 使用 spew 的最大优点是输出格式已经很好,因此您可以轻松检查所有对象属性。
【解决方案3】:

我的 2cents 将是使用 json.MarshalIndent - 很惊讶这不被建议,因为它是最直接的。例如:

func prettyPrint(i interface{}) string {
    s, _ := json.MarshalIndent(i, "", "\t")
    return string(s)
}

没有外部部门,输出格式很好。

【讨论】:

  • 有趣的选项。 +1
  • 正是我想要的。重用内置 json 库,轻松进行漂亮的打印。
  • 除非需要打印字段类型和长度(Spew 非常适合),否则此解决方案是最好的,因为指针也可以正确打印!
  • ?? 又短又甜。如果你想要空格缩进,你可以用" "替换"\t"
  • 注意,Marshal() 只序列化结构的导出字段——不过它非常适合映射。
【解决方案4】:

我认为如果您想要struct 的某种格式化输出,最好实现自定义字符串

例如

package main

    import "fmt"

    type Project struct {
        Id int64 `json:"project_id"`
        Title string `json:"title"`
        Name string `json:"name"`
    }

    func (p Project) String() string {
        return fmt.Sprintf("{Id:%d, Title:%s, Name:%s}", p.Id, p.Title, p.Name)
    }

    func main() {
        o := Project{Id: 4, Name: "hello", Title: "world"}
        fmt.Printf("%+v\n", o)
    }

【讨论】:

    【解决方案5】:
    p = Project{...}
    fmt.Printf("%+v", p)
    fmt.Printf("%#v", p) //with type
    

    【讨论】:

    • fmt.Printf(%#v, p) ,抛出我main.structstruct type "%#v""%+v" @cokebol 有什么区别
    【解决方案6】:

    或者,尝试使用此功能PrettyPrint()

    // print the contents of the obj
    func PrettyPrint(data interface{}) {
        var p []byte
        //    var err := error
        p, err := json.MarshalIndent(data, "", "\t")
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Printf("%s \n", p)
    }
    

    为了使用它,您不需要任何额外的包,除了fmtencoding/json,只需一个引用、指向或您创建的结构的文字。

    要使用你的结构,在 main 或你所在的任何包中初始化它,然后将它传递给PrettyPrint()

    type Prefix struct {
        Network string
        Mask    int
    }
    
    func valueStruct() {
        // struct as a value
        var nw Prefix
        nw.Network = "10.1.1.0"
        nw.Mask = 24
        fmt.Println("### struct as a pointer ###")
        PrettyPrint(&nw)
    }
    

    它的输出是

    ### struct as a pointer ###
    {
        "Network": "10.1.1.0",
        "Mask": 24
    } 
    

    使用代码here

    【讨论】:

      【解决方案7】:

      我建议使用Pretty Printer Library。因为你可以很容易地打印任何结构。

      1. 安装库

        https://github.com/kr/pretty

      go get github.com/kr/pretty
      

      现在在你的代码中这样做

      package main
      
      import (
      fmt
      github.com/kr/pretty
      )
      
      func main(){
      
      type Project struct {
          Id int64 `json:"project_id"`
          Title string `json:"title"`
          Name string `json:"name"`
          Data Data `json:"data"`
          Commits Commits `json:"commits"`
      }
      
      fmt.Printf("%# v", pretty.Formatter(Project)) //It will print all struct details
      
      fmt.Printf("%# v", pretty.Formatter(Project.Id)) //It will print component one by one.
      
      }
      

      您还可以通过这个库获得组件之间的差异等等。您也可以在这里查看库Docs

      【讨论】:

      • 看看pretty.Formatter生成的输出示例会很有帮助
      【解决方案8】:

      我喜欢litter

      来自他们的自述文件:

      type Person struct {
        Name   string
        Age    int
        Parent *Person
      }
      
      litter.Dump(Person{
        Name:   "Bob",
        Age:    20,
        Parent: &Person{
          Name: "Jane",
          Age:  50,
        },
      })
      

      Sdump 在测试中非常方便:

      func TestSearch(t *testing.T) {
        result := DoSearch()
      
        actual := litterOpts.Sdump(result)
        expected, err := ioutil.ReadFile("testdata.txt")
        if err != nil {
          // First run, write test data since it doesn't exist
              if !os.IsNotExist(err) {
            t.Error(err)
          }
          ioutil.Write("testdata.txt", actual, 0644)
          actual = expected
        }
        if expected != actual {
          t.Errorf("Expected %s, got %s", expected, actual)
        }
      }
      

      【讨论】:

        【解决方案9】:

        使用包fmt输出很方便:

        fmt.Printf("%+v \n", yourProject)
        

        如果要查看结构的完整类型,可以使用#replace +:

        fmt.Printf("%#v \n", yourProject) 
        

        【讨论】:

          【解决方案10】:

          当您有更复杂的结构时,您可能需要在打印前转换为 JSON:

          // Convert structs to JSON.
          data, err := json.Marshal(myComplexStruct)
          fmt.Printf("%s\n", data)
          

          来源:https://gist.github.com/tetsuok/4942960

          【讨论】:

            【解决方案11】:

            将结构打印为 JSON:

            fmt.Printf("%#v\n", yourProject)
            

            也可以使用(如上所述):

            fmt.Printf("%+v\n", yourProject)
            

            但第二个选项打印的字符串值不带“”,因此更难阅读。

            【讨论】:

              【解决方案12】:

              有时,将结构打印为有效的 Go 代码(go/ast 等效项)可能会很方便。为此,https://github.com/hexops/valast 做得很好:

              package main
              
              import (
                  "fmt"
              
                  "github.com/hexops/valast"
              )
              
              type ProjectData struct {
                  Title   string `json:"title"`
                  Name    string `json:"name"`
                  Data    string `json:"data"`
                  Commits string `json:"commits"`
              }
              
              type Project struct {
                  Id   int64        `json:"project_id"`
                  Data *ProjectData `json:"data"`
              }
              
              func main() {
                  p := Project{
                      Id: 1,
                      Data: &ProjectData{
                          Title:   "Test",
                          Name:    "Mihai",
                          Data:    "Some data",
                          Commits: "Test Message",
                      },
                  }
                  fmt.Println(valast.String(p))
              }
              

              输出:

              go run main.go 
              Project{Id: 1, Data: &ProjectData{
                      Title:   "Test",
                      Name:    "Mihai",
                      Data:    "Some data",
                      Commits: "Test Message",
              }}
              

              【讨论】:

              • go-spew 的有趣替代品。赞成。
              • 很遗憾,go-spew 似乎很久没有收到任何更新了。我相信它可能已经被放弃了。目前,它仍然可以使用。
              【解决方案13】:

              访问here 查看完整代码。在这里,您还将找到一个在线终端的链接,可以在其中运行完整的代码,该程序表示如何提取结构的信息(字段名称、它们的类型和值)。下面是只打印字段名称的程序 sn-p。

              package main
              
              import "fmt"
              import "reflect"
              
              func main() {
                  type Book struct {
                      Id    int
                      Name  string
                      Title string
                  }
              
                  book := Book{1, "Let us C", "Enjoy programming with practice"}
                  e := reflect.ValueOf(&book).Elem()
              
                  for i := 0; i < e.NumField(); i++ {
                      fieldName := e.Type().Field(i).Name
                      fmt.Printf("%v\n", fieldName)
                  }
              }
              
              /*
              Id
              Name
              Title
              */
              

              【讨论】:

                【解决方案14】:

                也许这不应该应用于生产请求,但如果您处于调试模式,我建议您遵循以下方法。

                marshalledText, _ := json.MarshalIndent(inputStruct, "", " ")
                fmt.Println(string(marshalledText))
                

                这导致将数据格式化为 json 格式,提高了可读性。

                【讨论】:

                • 上述方法有catch,必须导出struct属性。
                【解决方案15】:

                您可以先进行 json 编组并将其打印为字符串。在那里你可以完整地看到整个结构体的值。

                package main
                
                import "fmt"
                import "json"
                
                type Project struct {
                    Id int64 `json:"project_id"`
                    Title string `json:"title"`
                    Name string `json:"name"`
                }
                
                func main() {
                    o := Project{Id: 4, Name: "hello", Title: "world"}
                    om, _ := json.marshal(o)
                    log.Printf("%s\n", string(om))
                }
                

                【讨论】:

                  【解决方案16】:

                  还有go-render,它处理指针递归和大量用于字符串和整数映射的键排序。

                  安装:

                  go get github.com/luci/go-render/render
                  

                  例子:

                  type customType int
                  type testStruct struct {
                          S string
                          V *map[string]int
                          I interface{}
                  }
                  
                  a := testStruct{
                          S: "hello",
                          V: &map[string]int{"foo": 0, "bar": 1},
                          I: customType(42),
                  }
                  
                  fmt.Println("Render test:")
                  fmt.Printf("fmt.Printf:    %#v\n", a)))
                  fmt.Printf("render.Render: %s\n", Render(a))
                  

                  哪些打印:

                  fmt.Printf:    render.testStruct{S:"hello", V:(*map[string]int)(0x600dd065), I:42}
                  render.Render: render.testStruct{S:"hello", V:(*map[string]int){"bar":1, "foo":0}, I:render.customType(42)}
                  

                  【讨论】:

                    【解决方案17】:
                    fmt.Printf("%+v\n", project)
                    

                    这是打印细节的基本方式

                    【讨论】:

                      【解决方案18】:

                      不使用外部库并在每个字段后换行:

                      log.Println(
                                  strings.Replace(
                                      fmt.Sprintf("%#v", post), ", ", "\n", -1))
                      

                      【讨论】:

                        【解决方案19】:

                        非常简单 我没有数据和提交的结构所以我改变了

                        package main
                        
                        import (
                            "fmt"
                        )
                        
                        type Project struct {
                            Id      int64   `json:"project_id"`
                            Title   string  `json:"title"`
                            Name    string  `json:"name"`
                            Data    string  `json:"data"`
                            Commits string  `json:"commits"`
                        }
                        
                        func main() {
                            p := Project{
                            1,
                            "First",
                            "Ankit",
                            "your data",
                            "Commit message",
                            }
                            fmt.Println(p)
                        }
                        

                        为了学习,您可以从这里获得帮助:https://gobyexample.com/structs

                        【讨论】:

                          【解决方案20】:

                          如果您想写入日志文件,就像我之前搜索的那样。那么你应该使用:

                          log.Infof("Information %+v", structure)
                          

                          注意::这不适用于 log.Info 或 log.Debug。在这种情况下,将打印“%v”,并且将打印结构的所有值而不打印键/变量名称。

                          【讨论】:

                            【解决方案21】:

                            另一种方法是,创建一个名为toString 的函数,它采用结构,格式化 字段随心所欲。

                            import (
                                "fmt"
                            )
                            
                            type T struct {
                                x, y string
                            }
                            
                            func (r T) toString() string {
                                return "Formate as u need :" + r.x + r.y
                            }
                            
                            func main() {
                                r1 := T{"csa", "ac"}
                                fmt.Println("toStringed : ", r1.toString())
                            }
                            

                            【讨论】:

                            • 或者你可以实现Stringer接口。它看起来像这样:func (t T) String() string { return fmt.Sprintf("SomeT{TID: %d, TField: %d, SomeTField: %s, SomeAnotherField: %s}", t.ID, t.Field, t.SomeTField, t.SomeAnotherField) }
                            【解决方案22】:
                                type Response struct {
                                    UserId int    `json:"userId"`
                                    Id     int    `json:"id"`
                                    Title  string `json:"title"`
                                    Body   string `json:"body"`
                                }
                            
                                func PostsGet() gin.HandlerFunc {
                                    return func(c *gin.Context) {
                                        xs, err := http.Get("https://jsonplaceholder.typicode.com/posts")
                                        if err != nil {
                                            log.Println("The HTTP request failed with error: ", err)
                                        }
                                        data, _ := ioutil.ReadAll(xs`enter code here`.Body)
                            
                            
                                        // this will print the struct in console            
                                        fmt.Println(string(data))
                            
                            
                                        // this is to send as response for the API
                                        bytes := []byte(string(data))
                                        var res []Response
                                        json.Unmarshal(bytes, &res)
                            
                                        c.JSON(http.StatusOK, res)
                                    }
                                }
                            

                            【讨论】:

                              【解决方案23】:

                              这些包中的大多数都依赖于反射包来使这些事情成为可能。

                              fmt.Sprintf() 正在使用标准库的 -> func (p *pp) printArg(arg interface{}, verb rune)

                              转到第 638 行 -> https://golang.org/src/fmt/print.go

                              反思:

                              https://golang.org/pkg/reflect/

                              示例代码:

                              https://github.com/donutloop/toolkit/blob/master/debugutil/prettysprint.go

                              【讨论】:

                                【解决方案24】:
                                fmt.Println("%+v", structure variable)
                                

                                更好的方法是在名为“commons”的包中为字符串“%+v”创建一个全局常量(也许),并在代码中的任何地方使用它

                                //In commons package
                                const STRUCTURE_DATA_FMT = "%+v"
                                
                                //In your code everywhere
                                fmt.Println(commons.STRUCTURE_DATA_FMT, structure variable)
                                

                                【讨论】:

                                • 礼貌地,人们对此投了反对票,因为Println 函数不接受格式字符串参数。您说全局常量更好,但没有说明为什么它比标记的答案更好。您为众所周知的格式字符串创建了一个非标准标签。标签更长,更难记住,并且没有其他人会使用您的代码。它使用 ALL_CAPS 和下划线,每个 golang linter 都会抱怨。约定是 mixedCaps golang.org/doc/effective_go.html#mixed-caps 可能最好删除这个答案。
                                猜你喜欢
                                • 2011-02-14
                                • 2017-06-19
                                • 1970-01-01
                                • 1970-01-01
                                • 2019-04-13
                                • 2017-06-03
                                • 2018-11-24
                                • 2016-05-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多