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


379

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

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

2
所有这些,用于调试吗?尝试fmt.Println
Ry-

Answers:


639

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

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

fmt包装中

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

假设您有一个Project实例(位于“ yourProject”中)

文章JSON和Go将提供有关如何从JSON结构中检索值的更多详细信息。


“按示例进行搜索”页面提供了另一种技术:

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"]}

如果没有任何实例,则需要使用反射来显示给定结构的字段名称,如本例所示

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

1
感谢您的回答,但还有一件事。我的JSON文件与API相关...因此,我不想设置Id或Name,我只想通过API获取它并在控制台中打印它。我怎样才能做到这一点?
fnr 2014年

4
@fnr如果您有JSON文档,则需要先将其解组,然后才能打印其字段。
VonC

3
已投票!我的一个抱怨是%+ v命令不能很好地打印它!我仍然对这条线的效率感到满意。
Shadoninja '16

1
需要为json编组技术导入“ encoding / json”,
Jim Hoagland,

1
请注意,.Printf(“%+ v \ n”)也可与“ log”包一起使用
Ariel Monaco

139

我想推荐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) ""
}

5
您可以添加go-spew具有的取消引用功能。它允许您打印指针所引用的结构的值,而不是指针itsel的结构的值

使用spew的最大优点是输出已经格式化,因此您可以轻松检查所有对象属性。
线圈

97

我的2美分将被使用json.MarshalIndent-不建议这样做,因为这是最简单的方法。例如:

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

没有外部部门,并且可以很好地格式化输出。


2
有趣的选择。+1
VonC '18年

1
正是我想要的。通过重复使用内置的json库,轻松进行漂亮的打印。
AdmiralThrawn

除非需要打印字段类型和长度(Spew非常适合该字段),否则此解决方案是最好的,因为指针也已正确打印!
Christophe Vidal

👏🏻简短而甜美。如果您要缩进空格"\t"" "则可以替换为
Dana Woodman

1
值得注意的是,Marshal()仅序列化结构的导出字段-尽管它非常适合映射。
nobar

24

我认为,如果您想要某种格式的输出,最好实现自定义字符串 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)
    }

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

2
fmt.Printf(%#v, p),让我感到和@cokebol main.structstruct type 什么区别"%#v""%+v"
muthukumar helius

13

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

这里播放代码。


5

我喜欢垃圾

从他们的自述文件:

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

5

我建议使用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.

}

此外,您还可以通过该库获得组件之间的区别,等等。您也可以在这里查看图书馆文档


1
看看pretty.Formatter
Konstantin Tikhonov


3

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

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

2

还有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

另一种方法是,创建一个称为toStringstruct 的func ,并根据需要设置字段的格式。

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

2
或者您可以实现该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) }
rbo13


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

0

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

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


0

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

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

这导致以增强的可读性将数据格式化为json格式。



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

3
礼貌地,人们不赞成这样做,因为该Println函数不接受格式字符串参数。您说全局常数更好,但是还没有理由为什么它比标记答案好。您已经为众所周知的格式字符串创建了非标准标签。标签更长,更难记,任何在您的代码上工作的人都不会使用它。它同时使用ALL_CAPS和下划线,每个golang短毛猫都会抱怨。约定为mixedCaps golang.org/doc/effective_go.html#mixed-caps最好删除此答案。
达沃斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.