Wie drucke ich Strukturvariablen in der Konsole?


380

Wie kann ich (in der Konsole) der Druck Id, Title, Nameusw. diese Struktur 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"`
}

2
Alle zum Debuggen? Versuchen Sie es fmt.Println.
Ry-

Antworten:


640

So drucken Sie den Namen der Felder in einer Struktur:

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

Aus dem fmtPaket :

Beim Drucken von Strukturen %+vfügt das Plus-Flag ( ) Feldnamen hinzu

Angenommen, Sie haben eine Instanz von Project (in ' yourProject').

Der Artikel JSON und Go enthält weitere Informationen zum Abrufen der Werte aus einer JSON-Struktur.


Diese Beispielseite bietet eine andere Technik:

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

Das würde drucken:

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

Wenn Sie keine Instanz haben, müssen Sie Reflection verwenden , um den Namen des Felds einer bestimmten Struktur anzuzeigen, wie in diesem Beispiel .

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
Vielen Dank für Ihre Antwort, aber es gibt noch eine Sache. Meine JSON-Dateien beziehen sich auf eine API ... daher möchte ich die ID oder den Namen nicht festlegen, sondern nur über die API übertragen und in der Konsole drucken. Wie kann ich das machen?
Für den

4
@fnr Wenn Sie ein JSON-Dokument haben, müssen Sie es entfernen, bevor Sie das Feld drucken können.
VonC

3
Upvoted! Meine einzige Beschwerde ist, dass der Befehl% + v es nicht schön druckt! Ich bin immer noch zufrieden mit der Effizienz dieser Linie.
Shadoninja

1
Müssen Sie "encoding / json" für die json-Marshalling-Technik importieren,
Jim Hoagland

1
Beachten Sie, dass .Printf ("% + v \ n") auch mit dem "log" -Paket funktioniert
Ariel Monaco

139

Ich möchte go-spew empfehlen , das laut Github "einen sehr hübschen Drucker für Go-Datenstrukturen implementiert , um das Debuggen zu erleichtern".

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

Anwendungsbeispiel:

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

Ausgabe:

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

5
Sie können die Dereferenzierungsfunktion von go-spew hinzufügen. Es ermöglicht Ihnen, den Wert der Struktur zu drucken, auf die ein Zeiger verweist, und nicht den Zeiger selbst

Der große Vorteil bei der Verwendung von Spew ist, dass die Ausgabe bereits gut formatiert ist, sodass Sie alle Objekteigenschaften problemlos überprüfen können.
COil

97

Meine 2 Cent wären zu verwenden json.MarshalIndent- überrascht, dass dies nicht empfohlen wird, da es am einfachsten ist. zum Beispiel:

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

Keine externen Deps und führt zu einer gut formatierten Ausgabe.


2
Interessante Option. +1
VonC

1
Genau das, wonach ich gesucht habe. Einfaches hübsches Drucken mit Wiederverwendung der eingebauten JSON-Bibliothek.
AdmiralThrawn

Sofern man Feldtyp und Länge nicht drucken muss (Spew ist dafür großartig), ist diese Lösung einfach die beste, da Zeiger auch richtig gedruckt werden!
Christophe Vidal

👏🏻 Kurz und bündig. Sie können ersetzen "\t"mit , " "wenn Sie Platz Einrücken wollen statt
Dana Woodman

1
Bemerkenswert ist, dass Marshal()nur die exportierten Felder einer Struktur serialisiert werden - es ist jedoch perfekt für Karten.
Nobar

24

Ich denke, es wäre besser, einen benutzerdefinierten Stringer zu implementieren, wenn Sie eine formatierte Ausgabe von a wünschen struct

zum Beispiel

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), wirft mich main.structmit struct type was ist der Unterschied zwischen "%#v"und "%+v"@cokebol
muthukumar helius

13

Alternativ können Sie diese Funktion verwenden 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)
}

Um dies zu verwenden, benötigen Sie keine zusätzlichen Pakete mit Ausnahme von fmtund encoding/jsonlediglich einer Referenz, einem Zeiger oder einem Literal der von Ihnen erstellten Struktur.

Um es zu verwenden, nehmen Sie einfach Ihre Struktur, initialisieren Sie sie in main oder einem anderen Paket, in dem Sie sich befinden, und übergeben Sie sie 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)
}

Die Ausgabe wäre

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

Spielen Sie mit dem Code um hier .


5

Ich mag Müll .

Aus ihrer Readme:

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

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

Sdump ist ziemlich praktisch 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)
  }
}

5

Ich empfehle die Verwendung der Pretty Printer Library . Dadurch können Sie jede Struktur sehr einfach drucken.

  1. Bibliothek installieren

    https://github.com/kr/pretty

oder

go get github.com/kr/pretty

Tun Sie dies jetzt in Ihrem 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.

}

Durch diese Bibliothek und mehr können Sie auch Unterschiede zwischen Komponenten feststellen. Sie können auch einen Blick auf Bibliothek Docs hier.


1
Es wäre hilfreich, das Beispiel der Ausgabe zu sehen, die vonpretty.Formatter
Konstantin Tikhonov

4

Wenn Sie komplexere Strukturen haben, müssen Sie möglicherweise vor dem Drucken in JSON konvertieren:

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

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


3

Besuchen Sie hier , um den vollständigen Code zu sehen. Hier finden Sie auch einen Link für ein Online-Terminal, über das der vollständige Code ausgeführt werden kann und das Programm darstellt, wie die Informationen der Struktur extrahiert werden (Feldname, Typ und Wert). Unten finden Sie das Programm-Snippet, das nur die Feldnamen druckt.

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

Es gibt auch Go-Rendering , das die Zeigerrekursion und viele Schlüsselsortierungen für String- und Int-Maps übernimmt.

Installation:

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

Beispiel:

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

Welche Drucke:

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

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

Dies ist die grundlegende Methode zum Drucken der Details


0

Eine andere Möglichkeit besteht darin, eine Funktion mit dem Namen toStringstruct zu erstellen und die Felder nach Ihren Wünschen zu formatieren.

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
Oder Sie könnten die StringerSchnittstelle implementieren . Es würde 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) }
ungefähr

0

Ohne Verwendung externer Bibliotheken und mit neuer Zeile nach jedem Feld:

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

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

sehr einfach Ich habe nicht die Struktur von Daten und Commits Also habe ich die geändert

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

Informationen zum Lernen erhalten Sie hier: https://gobyexample.com/structs


0

Möglicherweise sollte dies nicht für Produktionsanforderungen angewendet werden, aber wenn Sie sich im Debugging-Modus befinden, empfehlen wir Ihnen, den folgenden Ansatz zu befolgen.

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

Dies führt zu einer Formatierung der Daten im JSON-Format mit verbesserter Lesbarkeit.



-7
fmt.Println("%+v", structure variable)

Ein besserer Weg, dies zu tun, wäre, eine globale Konstante für die Zeichenfolge "% + v" in einem Paket namens "commons" (möglicherweise) zu erstellen und sie überall in Ihrem Code zu verwenden

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

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

3
Politisch haben die Leute dies abgelehnt, weil die PrintlnFunktion kein Format-String-Argument akzeptiert. Sie sagen, eine globale Konstante ist besser, haben aber nicht gerechtfertigt, warum sie besser ist als die markierte Antwort. Sie haben eine nicht standardmäßige Beschriftung für eine bekannte Formatzeichenfolge erstellt. Das Etikett ist viel länger, schwerer zu merken und niemand anderes, der an Ihrem Code arbeitet, würde es verwenden. Es verwendet sowohl ALL_CAPS als auch einen Unterstrich, über den sich jeder Golang-Linter beschweren wird. Die Konvention lautet mixedCaps golang.org/doc/effective_go.html#mixed-caps. Am besten entfernen Sie diese Antwort.
Davos
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.