ChatGPT解决这个技术问题 Extra ChatGPT

如何在控制台中打印结构变量?

如何在 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"`
}
所有这些,用于调试?试试 fmt.Println
我真的很喜欢用 spew github.com/davecgh/go-spew
github.com/hexops/valast 是 go-spew 的一个很好的最新替代方案。

B
Benjamin W.

要打印结构中字段的名称:

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" 包
M
Martin Tournoij

我想推荐 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 的最大优点是输出已经格式化,因此您可以轻松检查所有对象属性。
m
mad.meesh

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

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

没有外部部门并产生格式良好的输出。


正是我想要的。通过重用内置的 json 库轻松进行漂亮的打印。
除非需要打印字段类型和长度(Spew 非常适合),否则此解决方案是最好的,因为指针也可以正确打印!
👏🏻短而甜。如果您想要空格缩进,您可以将 "\t" 替换为 " "
值得注意的是,Marshal() 仅序列化结构的导出字段——尽管它非常适合映射。
N
Nimantha

如果您想要某种格式的 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)
    }

c
cokeboL
p = Project{...}
fmt.Printf("%+v", p)
fmt.Printf("%#v", p) //with type

fmt.Printf(%#v, p) ,将 main.structstruct type 扔给我 "%#v""%+v" @cokebol 有什么区别
"%+v" :这将为您提供未编组的值及其字段名称。 "%#v" :这将给出值及其类型/签名。例如:p := Project{Id: 4, Name: "hello", Title: "world"} "%+v" 的输出: {Id:4 Title:world Name:hello} "%#v" 的输出: main.Project{Id:4, Title:"world", Name:"hello"}
E
Erik Toor

或者,尝试使用此功能 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


T
Tomerikoo

使用包 fmt 输出非常方便:

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

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

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

a
amku91

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

安装库 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 生成的输出示例会很有帮助
q
qed

我喜欢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)
  }
}

I
Ivan Gerasimenko

要将结构打印为 JSON:

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

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

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

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


C
Cassio

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

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

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


B
Brandon Heng

您可以先执行 json mashal 并将其打印为字符串。在那里你可以完全看到整个结构值。

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

这是一个很好的技术——我一直用它来调试。指针被取消引用,最常见的类型渲染得很好。
我相信是 import "encoding/json"json.Marshal(o)
M
Mihai Todor

有时,将结构打印为有效的 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 似乎很长时间没有收到任何更新。我相信它可能已经被放弃了。目前,它仍然可以使用。
h
hygull

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

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

F
Friska S E Putri

我建议使用 json.Unmarshal() 我尝试打印 id 并希望它有帮助:

var jsonString = `{"Id": 1, "Title": "the title", "Name": "the name","Data": "the data","Commits" : "the commits"}`
var jsonData = []byte(jsonString)

var data Project

var err = json.Unmarshal(jsonData, &data)
if err != nil {
    fmt.Println(err.Error())
    return
}

fmt.Println("Id :", data.Id)

m
mourya venkat

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

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

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


上述方法有一个问题,必须导出结构属性。
m
mdwhatcott

还有 go-render,它处理指针递归以及字符串和 int 映射的大量键排序。

安装:

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

0
0example.com
fmt.Printf("%+v\n", project)

这是打印细节的基本方式


A
Ankit Malik

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

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


A
Ayush

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

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

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


n
netskink

一个简单的问题有很多答案。我不妨把我的帽子扔进擂台。

package main

import "fmt"

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

var (
    Testy Project
)

func dump_project(foo Project) {
    fmt.Println("== Dump Project Struct ====")
    fmt.Printf("Id: %d\n", foo.Id)
    fmt.Println("Title: ", foo.Title)
    fmt.Printf("Name: %v\n", foo.Name)
}

func main() {
    fmt.Println("hello from go")
    Testy.Id = 3
    Testy.Title = "yo"
    Testy.Name = "my name"
    fmt.Println(Testy)
    dump_project(Testy)
}

各种打印方法的输出

hello from go
{3 yo my name}
== Dump Project Struct ====
Id: 3
Title:  yo
Name: my name

V
Vladimir Babin

不使用外部库并在每个字段后添加新行:

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

A
Aditya Singh Manhas
    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)
        }
    }

B
BartoszKP

另一种方法是,创建一个名为 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) }
D
Donutloop

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

https://i.stack.imgur.com/3h9Kr.png

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


J
Jithendra Kumar
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 可能最好删除此答案。