Risposte:
Per stampare il nome dei campi in una struttura:
fmt.Printf("%+v\n", yourProject)
Dal fmt
pacchetto :
quando si stampano le strutture, il flag più (
%+v
) aggiunge i nomi dei campi
Ciò suppone che tu abbia un'istanza di Project (in ' yourProject
')
L'articolo JSON e Go forniranno maggiori dettagli su come recuperare i valori da una struttura JSON.
Questa pagina Vai all'esempio fornisce un'altra tecnica:
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))
Che stamperebbe:
{"page":1,"fruits":["apple","peach","pear"]}
Se non si dispone di alcuna istanza, è necessario utilizzare reflection per visualizzare il nome del campo di una determinata struttura, come in questo esempio .
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())
}
Voglio raccomandare go-spew , che secondo il loro github "Implementa una stampante piuttosto profonda per le strutture dati Go per facilitare il debug"
go get -u github.com/davecgh/go-spew/spew
esempio di utilizzo:
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)
}
produzione:
(main.Project) {
Id: (int64) 0,
Title: (string) (len=5) "world",
Name: (string) (len=5) "hello",
Data: (string) "",
Commits: (string) ""
}
i miei 2 centesimi sarebbero da usare json.MarshalIndent
- sorpreso che questo non sia suggerito, in quanto è il più semplice. per esempio:
func prettyPrint(i interface{}) string {
s, _ := json.MarshalIndent(i, "", "\t")
return string(s)
}
nessun deps esterno e produce un output ben formattato.
"\t"
con " "
se vuoi invece rientrare nello spazio
Penso che sarebbe meglio implementare uno stringer personalizzato se si desidera un tipo di output formattato di a struct
per esempio
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)
}
p = Project{...}
fmt.Printf("%+v", p)
fmt.Printf("%#v", p) //with type
fmt.Printf(%#v, p)
, mi lancia main.struct
con struct type
qual è la differenza tra "%#v"
e "%+v"
@cokebol
In alternativa, prova a utilizzare questa funzione 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)
}
Per usarlo non hai bisogno di pacchetti aggiuntivi ad eccezione di , fmt
e encoding/json
solo un riferimento, un puntatore o letterale della struttura che hai creato.
Per usare basta prendere la tua struttura, inizializzarla nel pacchetto principale o in qualunque altro pacchetto e passarla 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)
}
Il suo output sarebbe
### struct as a pointer ###
{
"Network": "10.1.1.0",
"Mask": 24
}
Gioca con il codice qui .
Mi piacciono i rifiuti .
Dal loro readme:
type Person struct {
Name string
Age int
Parent *Person
}
litter.Dump(Person{
Name: "Bob",
Age: 20,
Parent: &Person{
Name: "Jane",
Age: 50,
},
})
Sdump
è abbastanza utile nei test:
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)
}
}
Consiglio di usare Pretty Printer Library . In questo puoi stampare qualsiasi struttura molto facilmente.
Installa libreria
o
go get github.com/kr/pretty
Ora fai così nel tuo codice
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.
}
Inoltre puoi ottenere la differenza tra i componenti attraverso questa libreria e molto altro. Puoi anche dare un'occhiata alla libreria Documenti qui.
pretty.Formatter
Quando si hanno strutture più complesse, potrebbe essere necessario convertire in JSON prima di stampare:
// Convert structs to JSON.
data, err := json.Marshal(myComplexStruct)
fmt.Printf("%s\n", data)
Visita qui per vedere il codice completo. Qui troverai anche un collegamento per un terminale online in cui è possibile eseguire il codice completo e il programma rappresenta come estrarre le informazioni sulla struttura (nome del campo, tipo e valore). Di seguito è riportato il frammento di programma che stampa solo i nomi dei campi.
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
*/
C'è anche go-render , che gestisce la ricorsione del puntatore e un sacco di ordinamento delle chiavi per le stringhe e le mappe int.
Installazione:
go get github.com/luci/go-render/render
Esempio:
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))
Che stampa:
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)}
fmt.Printf("%+v\n", project)
Questo è il modo di base per stampare i dettagli
Un altro modo è, creare una funzione chiamata toString
che richiede struct, formattare i campi come si desidera.
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
interfaccia. Sarebbe simile a questo: 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) }
Senza utilizzare librerie esterne e con una nuova riga dopo ogni campo:
log.Println(
strings.Replace(
fmt.Sprintf("%#v", post), ", ", "\n", -1))
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)
}
}
molto semplice Non ho la struttura di dati e commit Quindi ho cambiato il
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)
}
Per l'apprendimento puoi chiedere aiuto da qui: https://gobyexample.com/structs
Forse questo non dovrebbe essere applicato per le richieste di produzione ma se sei in modalità debug ti suggerisco di seguire l'approccio seguente.
marshalledText, _ := json.MarshalIndent(inputStruct, "", " ")
fmt.Println(string(marshalledText))
Ciò comporta la formattazione dei dati in formato json con una maggiore leggibilità.
La maggior parte di questi pacchetti fa affidamento sul pacchetto di riflessione per rendere possibili tali cose.
fmt.Sprintf () sta usando -> func (p * pp) printArg (interfaccia arg {}, runa verbo) di lib standard
Vai alla riga 638 -> https://golang.org/src/fmt/print.go
Riflessione:
https://golang.org/pkg/reflect/
Codice di esempio:
https://github.com/donutloop/toolkit/blob/master/debugutil/prettysprint.go
fmt.Println("%+v", structure variable)
Un modo migliore per farlo sarebbe quello di creare una costante globale per la stringa "% + v" in un pacchetto chiamato "commons" (forse) e usarla ovunque nel tuo codice
//In commons package
const STRUCTURE_DATA_FMT = "%+v"
//In your code everywhere
fmt.Println(commons.STRUCTURE_DATA_FMT, structure variable)
Println
funzione non accetta un argomento di stringa di formato. Dici che una costante globale è migliore ma non hai giustificato il motivo per cui è migliore della risposta contrassegnata. Hai creato un'etichetta non standard per una stringa di formato ben nota. L'etichetta è molto più lunga, più difficile da ricordare e nessun altro che lavora sul tuo codice lo userebbe. Utilizza sia ALL_CAPS sia un carattere di sottolineatura di cui ogni linter golang si lamenterà. La convenzione è mixedCaps
golang.org/doc/effective_go.html#mixed-caps Probabilmente è meglio rimuovere questa risposta.
fmt.Println
.