Jawaban:
Untuk mencetak nama bidang dalam sebuah struct:
fmt.Printf("%+v\n", yourProject)
Dari fmt
paket :
saat mencetak struct, tanda tambah (
%+v
) menambahkan nama bidang
Itu seandainya Anda memiliki instance dari Proyek (dalam ' yourProject
')
Artikel JSON dan Go akan memberikan rincian lebih lanjut tentang cara mengambil nilai dari struct JSON.
Halaman Go by example ini menyediakan teknik lain:
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))
Itu akan mencetak:
{"page":1,"fruits":["apple","peach","pear"]}
Jika Anda tidak memiliki instance, maka Anda perlu menggunakan refleksi untuk menampilkan nama bidang struct yang diberikan, seperti dalam contoh ini .
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())
}
Saya ingin merekomendasikan go-spew , yang menurut github mereka "Menerapkan printer yang cukup dalam untuk struktur data Go untuk membantu debugging"
go get -u github.com/davecgh/go-spew/spew
contoh penggunaan:
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)
}
keluaran:
(main.Project) {
Id: (int64) 0,
Title: (string) (len=5) "world",
Name: (string) (len=5) "hello",
Data: (string) "",
Commits: (string) ""
}
2 sen saya akan digunakan json.MarshalIndent
- terkejut ini tidak disarankan, karena ini adalah yang paling mudah. sebagai contoh:
func prettyPrint(i interface{}) string {
s, _ := json.MarshalIndent(i, "", "\t")
return string(s)
}
tidak ada deps eksternal dan menghasilkan output yang diformat dengan baik.
"\t"
dengan " "
jika Anda menginginkan indentasi ruang
Saya pikir akan lebih baik untuk menerapkan stringer kustom jika Anda ingin semacam output yang diformat dari struct
sebagai contoh
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)
, melempar saya main.struct
dengan struct type
apa perbedaan antara "%#v"
dan "%+v"
@cokebol
Atau, coba gunakan fungsi ini 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)
}
Untuk menggunakan ini, Anda tidak perlu paket tambahan dengan pengecualian fmt
dan encoding/json
, hanya referensi, pointer ke, atau literal dari struct yang telah Anda buat.
Untuk menggunakan, ambil saja struct Anda, inisialisasinya dalam paket utama atau apa pun yang Anda masuki dan berikan 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)
}
Keluarannya adalah
### struct as a pointer ###
{
"Network": "10.1.1.0",
"Mask": 24
}
Main-main dengan kode di sini .
Saya suka sampah .
Dari readme mereka:
type Person struct {
Name string
Age int
Parent *Person
}
litter.Dump(Person{
Name: "Bob",
Age: 20,
Parent: &Person{
Name: "Jane",
Age: 50,
},
})
Sdump
sangat berguna dalam tes:
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)
}
}
Saya merekomendasikan untuk menggunakan Perpustakaan Pretty Printer . Anda dapat mencetak struct dengan sangat mudah.
Instal Perpustakaan
atau
go get github.com/kr/pretty
Sekarang lakukan seperti ini dalam kode Anda
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.
}
Anda juga bisa mendapatkan perbedaan antara komponen melalui perpustakaan ini dan banyak lagi. Anda juga dapat melihat pustaka Documents di sini.
pretty.Formatter
Ketika Anda memiliki struktur yang lebih kompleks, Anda mungkin perlu mengonversi ke JSON sebelum mencetak:
// Convert structs to JSON.
data, err := json.Marshal(myComplexStruct)
fmt.Printf("%s\n", data)
Kunjungi di sini untuk melihat kode lengkap. Di sini Anda juga akan menemukan tautan untuk terminal daring tempat kode lengkap dapat dijalankan dan program tersebut menunjukkan cara mengekstraksi informasi struktur (beri isian jenis & nilainya). Di bawah ini adalah cuplikan program yang hanya mencetak nama bidang.
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
*/
Ada juga go-render , yang menangani rekursi pointer dan banyak pemilahan kunci untuk string dan peta int.
Instalasi:
go get github.com/luci/go-render/render
Contoh:
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))
Yang mencetak:
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)
Ini adalah cara dasar untuk mencetak detail
Cara lain adalah, buat fungsi toString
yang membutuhkan struct, format bidang seperti yang Anda inginkan.
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
antarmuka. Akan terlihat seperti ini: 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) }
Tanpa menggunakan perpustakaan eksternal dan dengan baris baru setelah setiap bidang:
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)
}
}
sangat sederhana Saya tidak memiliki struktur Data dan Komit. Jadi saya mengubah
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)
}
Untuk belajar, Anda dapat mengambil bantuan dari sini: https://gobyexample.com/structs
Mungkin ini seharusnya tidak diterapkan untuk permintaan produksi tetapi jika Anda berada pada mode debugging saya sarankan Anda mengikuti pendekatan di bawah ini.
marshalledText, _ := json.MarshalIndent(inputStruct, "", " ")
fmt.Println(string(marshalledText))
Ini menghasilkan format data dalam format json dengan peningkatan keterbacaan.
Sebagian besar paket-paket ini mengandalkan paket refleksi untuk memungkinkan hal-hal seperti itu terjadi.
fmt.Sprintf () menggunakan -> func (p * pp) printArg (antarmuka arg {{, verba rune) dari lib standar
Pergi ke baris 638 -> https://golang.org/src/fmt/print.go
Refleksi:
https://golang.org/pkg/reflect/
Kode contoh:
https://github.com/donutloop/toolkit/blob/master/debugutil/prettysprint.go
fmt.Println("%+v", structure variable)
Cara yang lebih baik untuk melakukan ini adalah membuat konstanta global untuk string "% + v" dalam paket yang disebut "commons" (mungkin) dan menggunakannya di mana saja dalam kode Anda
//In commons package
const STRUCTURE_DATA_FMT = "%+v"
//In your code everywhere
fmt.Println(commons.STRUCTURE_DATA_FMT, structure variable)
Println
fungsinya tidak menerima argumen format string. Anda mengatakan konstanta global lebih baik tetapi belum membenarkan mengapa itu lebih baik daripada jawaban yang ditandai. Anda telah membuat label tidak standar untuk string format yang terkenal. Label jauh lebih lama, lebih sulit untuk diingat dan tidak ada orang lain yang bekerja pada kode Anda yang akan menggunakannya. Ini menggunakan ALL_CAPS dan garis bawah yang akan dikeluhkan oleh setiap golang. Konvensi ini adalah mixedCaps
golang.org/doc/effective_go.html#mixed-caps Mungkin yang terbaik untuk menghapus jawaban ini.
fmt.Println
.