Ответы:
Чтобы напечатать название полей в структуре:
fmt.Printf("%+v\n", yourProject)
Из fmt
пакета :
при печати структур, флаг плюс (
%+v
) добавляет имена полей
Это предполагает, что у вас есть экземпляр Project (в ' yourProject
')
В статье JSON and Go будет дано больше подробностей о том, как извлечь значения из структуры JSON.
Эта страница Go by example предоставляет другую технику:
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())
}
Я хочу порекомендовать 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) ""
}
мой 2cents должен был бы использовать json.MarshalIndent
- удивленный, это не предложено, поскольку это является самым прямым. например:
func prettyPrint(i interface{}) string {
s, _ := json.MarshalIndent(i, "", "\t")
return string(s)
}
нет внешних депов и приводит к красиво отформатированному выводу.
"\t"
на, " "
если вместо этого хотите сделать отступ в пространстве
Я думаю, что было бы лучше реализовать пользовательский стрингер, если вы хотите какой-то форматированный вывод 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)
}
p = Project{...}
fmt.Printf("%+v", p)
fmt.Printf("%#v", p) //with type
fmt.Printf(%#v, p)
, Бросает меня main.struct
с struct type
чем разница между "%#v"
и "%+v"
@cokebol
Или попробуйте использовать эту функцию 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)
}
Для того, чтобы использовать это, вам не нужны никакие дополнительные пакеты за исключением fmt
и encoding/json
, просто ссылка, указатель или литерал созданной вами структуры.
Для использования просто возьмите свою структуру, инициализируйте ее в основном или любом другом пакете, в котором вы находитесь, и передайте его в 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
}
Поиграйте с кодом здесь .
Я люблю мусор .
Из их readme:
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)
}
}
Я рекомендую использовать Pretty Printer Library . В этом вы можете распечатать любую структуру очень легко.
Установить библиотеку
или
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.
}
Также вы можете получить разницу между компонентами через эту библиотеку и многое другое. Вы также можете посмотреть библиотечные документы здесь.
pretty.Formatter
Если у вас есть более сложные структуры, вам может потребоваться преобразовать в JSON перед печатью:
// Convert structs to JSON.
data, err := json.Marshal(myComplexStruct)
fmt.Printf("%s\n", data)
Источник: https://gist.github.com/tetsuok/4942960
Посетите здесь, чтобы увидеть полный код. Здесь вы также найдете ссылку для онлайн-терминала, где можно запустить полный код и программа показывает, как извлечь информацию о структуре (имя поля, его тип и значение). Ниже приведен фрагмент программы, который печатает только имена полей.
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
*/
Также есть go-render , который обрабатывает рекурсию указателя и много сортирует ключи для строковых и целевых карт.
Установка:
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)}
fmt.Printf("%+v\n", project)
Это основной способ печати деталей
Другой способ - создать функцию с именем toString
struct, которая принимает структуру, форматировать поля по своему усмотрению.
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
интерфейс. Это будет выглядеть примерно так: 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) }
Без использования внешних библиотек и с новой строкой после каждого поля:
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)
}
}
очень просто у меня нет структуры данных и коммитов, поэтому я изменил
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
Возможно, это не должно применяться к производственным запросам, но если вы находитесь в режиме отладки, я предлагаю вам придерживаться следующего подхода.
marshalledText, _ := json.MarshalIndent(inputStruct, "", " ")
fmt.Println(string(marshalledText))
Это приводит к форматированию данных в формате json с повышенной удобочитаемостью.
Большинство этих пакетов полагаются на пакет отражения, чтобы сделать такие вещи возможными.
fmt.Sprintf () использует -> func (p * pp) printArg (интерфейс arg {}, глагол rune) стандартного lib
Перейдите на линию 638 -> https://golang.org/src/fmt/print.go.
Отражение:
https://golang.org/pkg/reflect/
Пример кода:
https://github.com/donutloop/toolkit/blob/master/debugutil/prettysprint.go
fmt.Println("%+v", structure variable)
Лучший способ сделать это - создать глобальную константу для строки «% + v» в пакете с именем «commons» (возможно) и использовать ее повсюду в вашем коде.
//In commons package
const STRUCTURE_DATA_FMT = "%+v"
//In your code everywhere
fmt.Println(commons.STRUCTURE_DATA_FMT, structure variable)
Println
функция не принимает аргумент строки формата. Вы говорите, что глобальная константа лучше, но не обосновывает, почему она лучше, чем отмеченный ответ. Вы создали нестандартную метку для хорошо известной строки формата. Метка намного длиннее, ее труднее запомнить, и никто, кто работает над вашим кодом, не будет ее использовать. Он использует как ALL_CAPS, так и символ подчеркивания, на который будет жаловаться каждый golang linter. Соглашение mixedCaps
гласит golang.org/doc/effective_go.html#mixed-caps Вероятно, лучше всего удалить этот ответ.
fmt.Println
.