ChatGPT解决这个技术问题 Extra ChatGPT

How to print struct variables in console?

How can I print (to the console) the Id, Title, Name, etc. of this struct in 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"`
}
All of them, for debugging? Try fmt.Println.
I really like to use spew github.com/davecgh/go-spew
github.com/hexops/valast is a good up-to-date alternative to go-spew.

B
Benjamin W.

To print the name of the fields in a struct:

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

From the fmt package:

when printing structs, the plus flag (%+v) adds field names

That supposes you have an instance of Project (in 'yourProject')

The article JSON and Go will give more details on how to retrieve the values from a JSON struct.

This Go by example page provides another technique:

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

That would print:

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

If you don't have any instance, then you need to use reflection to display the name of the field of a given struct, 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())
}

Thanks for your answer but there is one more thing. My JSON files are related to an API... therefor I dont want to set the Id or Name, I just want to get it over the API and print it in console. How can I do that?
@fnr If you have a JSON document, you would need to unmarshall it, before being able to print its field.
Upvoted! My one complaint is the %+v command does not pretty print it! I am still happy with the efficiency of this line.
Need to do import "encoding/json" for the json marshalling technique,
Note that .Printf("%+v\n") also works with the "log" package
M
Martin Tournoij

I want to recommend go-spew, which according to their github "Implements a deep pretty printer for Go data structures to aid in debugging"

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

usage example:

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

output:

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

you could add the dereference feature that go-spew has. It allows you to print the value of the struct where a pointer is referencing and not the pointer itsel
The big pro with use spew is that the output is already well formatted so you can easily check all the object properties.
m
mad.meesh

my 2cents would be to use json.MarshalIndent -- surprised this isn't suggested, as it is the most straightforward. for example:

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

no external deps and results in nicely formatted output.


Exactly what I was looking for. Easy pretty printing with reuse of built in json library.
Unless one needs to print field type and length (Spew is great for that), this solution is just the best as Pointers are also properly printed!
👏🏻 Short and sweet. You can replace "\t" with " " if you want space indenting instead
Of note, Marshal() only serializes the exported fields of a struct -- it's perfect for maps though.
N
Nimantha

I think it would be better to implement a custom stringer if you want some kind of formatted output of a struct

for example

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) , throws me main.struct with struct type what is the difference between "%#v" and "%+v" @cokebol
"%+v" : This will give you the un-marshalled value along with their field-names. "%#v" : This will give the values along with their type/signatures. For eg: p := Project{Id: 4, Name: "hello", Title: "world"} output for "%+v": {Id:4 Title:world Name:hello} output for "%#v": main.Project{Id:4, Title:"world", Name:"hello"}
E
Erik Toor

Alternatively, try using this function 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)
}

In order to use this you do not need any additional packages with the exception of fmt and encoding/json, just a reference, pointer to, or literal of the struct you have created.

To use just take your struct, initialize it in main or whatever package you are in and pass it into 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)
}

It's output would be

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

Play around with the code here.


T
Tomerikoo

It is very convenient to use package fmt to output:

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

if you want to see the full type of the sturct, you can use # replace + :

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

a
amku91

I recommend to use Pretty Printer Library. In that you can print any struct very easily.

Install Library https://github.com/kr/pretty

or

go get github.com/kr/pretty

Now do like this in your code

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.

}

Also you can get difference between component through this library and so more. You can also have a look on library Docs here.


Would be helpful to see the example of the output generated by pretty.Formatter
q
qed

I like litter.

From their readme:

type Person struct {
  Name   string
  Age    int
  Parent *Person
}

litter.Dump(Person{
  Name:   "Bob",
  Age:    20,
  Parent: &Person{
    Name: "Jane",
    Age:  50,
  },
})

Sdump is pretty handy in tests:

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

To print the struct as JSON:

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

Also possible with (as it was mentioned above):

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

But the second option prints string values without "" so it is harder to read.


C
Cassio

When you have more complex structures, you might need to convert to JSON before printing:

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

Source: https://gist.github.com/tetsuok/4942960


B
Brandon Heng

You can do the json mashal first and print it as a string. There you can see it the whole struct value completely.

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

This is a good technique - I use it for debugging all the time. pointers are dereferenced and most common types render well.
I believe it's import "encoding/json" and json.Marshal(o)?
M
Mihai Todor

Sometimes, it might be handy to print the struct as valid Go code (the go/ast equivalent). For this purpose, https://github.com/hexops/valast does a great job:

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

Output:

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

Sadly, it looks like go-spew hasn't received any updates in a long time. I believe it might have been abandoned. For now, it's still functional though.
h
hygull

Visit here to see the complete code. Here you will also find a link for an online terminal where the complete code can be run and the program represents how to extract structure's information(field's name their type & value). Below is the program snippet that only prints the field names.

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

i suggest to use json.Unmarshal() i try to print the id with this hope its helpfull:

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

Maybe this shouldn't be applied for production requests but if you are on debugging mode I suggest you follow the below approach.

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

This results in formatting the data in json format with increased readability.


There is catch in above approach, struct attributes must be exported.
m
mdwhatcott

There's also go-render, which handles pointer recursion and lots of key sorting for string and int maps.

Installation:

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

Example:

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

Which prints:

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)

This is the basic way of printing the details


A
Ankit Malik

very simple I don't have the structure of Data and Commits So I changed the

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

For learning you can take help from here : https://gobyexample.com/structs


A
Ayush

If you want to write in a log file, as I was searching previously. Then you should use:

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

Note:: This will not work with log.Info or log.Debug. In this case, "%v" will get printed, and all the values of the structure will be printed without printing the key/variable name.


n
netskink

A lot of answers for a simple question. I might as well throw my hat in the ring.

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

The output of the various print methods

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

V
Vladimir Babin

Without using external libraries and with new line after each field:

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

Another way is, create a func called toString that takes struct, format the fields as you wish.

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

Or you could implement the Stringer interface. It would look something like this: 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

Most of these packages are relying on the reflect package to make such things possible.

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

fmt.Sprintf() is using -> func (p *pp) printArg(arg interface{}, verb rune) of standard lib

Go to line 638 -> https://golang.org/src/fmt/print.go

Reflection:

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

Example code:

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


J
Jithendra Kumar
fmt.Println("%+v", structure variable)

A better way to do this would be to create a global constant for the string "%+v" in a package called "commons"(maybe) and use it everywhere in your code

//In commons package
const STRUCTURE_DATA_FMT = "%+v"

//In your code everywhere
fmt.Println(commons.STRUCTURE_DATA_FMT, structure variable)

Politely, people have down-voted this because the Println function doesn't accept a format string argument. You say a global constant is better but haven't justified why it is better than the marked answer. You have created a nonstandard label for a well known format string. The label is much longer, harder to remember and no-one else who works on your code would use it. It uses both ALL_CAPS and an underscore which every golang linter will complain about. The convention is mixedCaps golang.org/doc/effective_go.html#mixed-caps Probably best to remove this answer.