Respuestas:
Para imprimir el nombre de los campos en una estructura:
fmt.Printf("%+v\n", yourProject)
Del fmt
paquete :
al imprimir estructuras, el indicador más (
%+v
) agrega nombres de campo
Eso supone que tiene una instancia de Proyecto (en ' yourProject
')
El artículo JSON and Go dará más detalles sobre cómo recuperar los valores de una estructura JSON.
Esta página de ejemplo de Ir proporciona otra técnica:
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))
Eso imprimiría:
{"page":1,"fruits":["apple","peach","pear"]}
Si no tiene ninguna instancia, debe usar la reflexión para mostrar el nombre del campo de una estructura dada, como en este ejemplo .
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())
}
Quiero recomendar go-spew , que según su github "Implementa una impresora bastante profunda para estructuras de datos Go para ayudar en la depuración"
go get -u github.com/davecgh/go-spew/spew
ejemplo de uso:
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)
}
salida:
(main.Project) {
Id: (int64) 0,
Title: (string) (len=5) "world",
Name: (string) (len=5) "hello",
Data: (string) "",
Commits: (string) ""
}
mis 2 centavos serían para usar json.MarshalIndent
, me sorprende que esto no se sugiera, ya que es el más sencillo. por ejemplo:
func prettyPrint(i interface{}) string {
s, _ := json.MarshalIndent(i, "", "\t")
return string(s)
}
sin deps externos y resultados en una salida bien formateada.
"\t"
con " "
si quiere sangría espacial en su lugar
Creo que sería mejor implementar un stringer personalizado si desea algún tipo de salida formateada de un struct
por ejemplo
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)
, me arroja main.struct
con struct type
cuál es la diferencia entre "%#v"
y "%+v"
@cokebol
Alternativamente, intente usar esta función 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)
}
Para usar esto, no necesita ningún paquete adicional con la excepción de , fmt
y encoding/json
solo una referencia, puntero o literal de la estructura que ha creado.
Para usar solo tome su estructura, inicialícela en main o en cualquier paquete en el que se encuentre y páselo 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)
}
Su salida sería
### struct as a pointer ###
{
"Network": "10.1.1.0",
"Mask": 24
}
Juega un poco con el código aquí .
Me gusta la basura .
De su léame:
type Person struct {
Name string
Age int
Parent *Person
}
litter.Dump(Person{
Name: "Bob",
Age: 20,
Parent: &Person{
Name: "Jane",
Age: 50,
},
})
Sdump
es bastante útil en las pruebas:
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)
}
}
Recomiendo usar Pretty Printer Library . En eso puedes imprimir cualquier estructura muy fácilmente.
Instalar biblioteca
o
go get github.com/kr/pretty
Ahora haz esto en tu código
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.
}
También puede obtener la diferencia entre el componente a través de esta biblioteca y mucho más. También puede consultar la biblioteca de documentos aquí.
pretty.Formatter
Cuando tenga estructuras más complejas, es posible que necesite convertir a JSON antes de imprimir:
// Convert structs to JSON.
data, err := json.Marshal(myComplexStruct)
fmt.Printf("%s\n", data)
Visita aquí para ver el código completo. Aquí también encontrará un enlace para un terminal en línea donde se puede ejecutar el código completo y el programa representa cómo extraer la información de la estructura (nombre del campo, su tipo y valor). A continuación se muestra el fragmento de programa que solo imprime los nombres de campo.
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
*/
También hay go-render , que maneja la recursividad del puntero y mucha clasificación de claves para cadenas y mapas int.
Instalación:
go get github.com/luci/go-render/render
Ejemplo:
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))
Que imprime:
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)
Esta es la forma básica de imprimir los detalles.
Otra forma es crear un func llamado toString
que tome struct, formatear los campos como desee.
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
interfaz. Se vería así: 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) }
Sin usar bibliotecas externas y con una nueva línea después de cada 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)
}
}
muy simple no tengo la estructura de datos y confirmaciones, así que cambié el
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)
}
Para aprender, puede obtener ayuda desde aquí: https://gobyexample.com/structs
Tal vez esto no debería aplicarse a las solicitudes de producción, pero si está en modo de depuración, le sugiero que siga el siguiente enfoque.
marshalledText, _ := json.MarshalIndent(inputStruct, "", " ")
fmt.Println(string(marshalledText))
Esto da como resultado el formateo de los datos en formato json con mayor legibilidad.
La mayoría de estos paquetes se basan en el paquete reflect para hacer que tales cosas sean posibles.
fmt.Sprintf () está utilizando -> func (p * pp) printArg (interfaz arg {}, verbo rune) de lib estándar
Vaya a la línea 638 -> https://golang.org/src/fmt/print.go
Reflexión:
https://golang.org/pkg/reflect/
Código de ejemplo:
https://github.com/donutloop/toolkit/blob/master/debugutil/prettysprint.go
fmt.Println("%+v", structure variable)
Una mejor manera de hacer esto sería crear una constante global para la cadena "% + v" en un paquete llamado "commons" (quizás) y usarla en todas partes en su código
//In commons package
const STRUCTURE_DATA_FMT = "%+v"
//In your code everywhere
fmt.Println(commons.STRUCTURE_DATA_FMT, structure variable)
Println
función no acepta un argumento de cadena de formato. Dices que una constante global es mejor pero no has justificado por qué es mejor que la respuesta marcada. Ha creado una etiqueta no estándar para una cadena de formato conocida. La etiqueta es mucho más larga, más difícil de recordar y nadie más que trabaje en su código la usaría. Utiliza ALL_CAPS y un guión bajo del cual todos los Golang Linter se quejarán. La convención es mixedCaps
golang.org/doc/effective_go.html#mixed-caps Probablemente sea mejor eliminar esta respuesta.
fmt.Println
.