Konsolda yapı değişkenleri nasıl yazdırılır?


380

Nasıl (konsolunda) yazdırabilirsiniz Id, Title, Namevb Golang içinde struct'ın?

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
Hepsi hata ayıklama için mi? Deneyin fmt.Println.
Ry-

Yanıtlar:


640

Bir yapıdaki alanların adını yazdırmak için:

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

Gönderen fmtpaketin :

yapılar yazdırılırken, artı bayrağı ( %+v) alan adları ekler

Bu, bir Proje örneğiniz olduğunu varsayar (' yourProject' içinde)

JSON ve Go makalesi , değerlerin bir JSON yapısından nasıl alınacağı hakkında daha fazla ayrıntı verecektir.


Bu Örnekle Git sayfası başka bir teknik sağlar:

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

Bu yazdırır:

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

Herhangi bir örneğiniz yoksa , bu örnekte olduğu gibi, belirli bir yapıdaki alanın adını görüntülemek için yansıma kullanmanız gerekir .

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
Cevabınız için teşekkürler ama bir şey daha var. JSON dosyalarım bir API ile ilgili ... bu nedenle Id veya Adı ayarlamak istemiyorum, sadece API üzerinden almak ve konsolda yazdırmak istiyorum. Bunu nasıl yapabilirim?
fnr

4
@fnr Bir JSON belgeniz varsa, alanını yazdırabilmeniz için onun işaretini kaldırmanız gerekir.
VonC

3
Upvoted! Benim tek şikayet% + v komut güzel yazdırmak değil! Bu hattın verimliliğinden hala memnunum.
Shadoninja

1
Json marshalling tekniği için ithalat "kodlama / json" yapmak gerekiyor,
Jim Hoagland

1
.Printf ("% + v \ n") "log" paketiyle de çalışır
Ariel Monaco

139

Github'a göre "Go veri yapılarının hata ayıklamaya yardımcı olması için derin ve güzel bir yazıcı uygular" adlı go-spew'i tavsiye etmek istiyorum.

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

kullanım örneği:

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

çıktı:

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

5
go-spew'in sahip olduğu dereference özelliğini ekleyebilirsiniz. Bir işaretçiyi referans aldığı değil, bir işaretçinin referans aldığı yapının değerini yazdırmanıza olanak tanır

Spew kullanımıyla büyük profesyonel, çıktının zaten iyi biçimlendirilmiş olmasıdır, böylece tüm nesne özelliklerini kolayca kontrol edebilirsiniz.
Bobin

97

benim 2 sent kullanmak olacaktır json.MarshalIndent- en basit olduğu için bu önerilmiyor şaşırttı. Örneğin:

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

harici deps yok ve güzel biçimlendirilmiş çıktı ile sonuçlanır.


2
İlginç bir seçenek. +1
VonC

1
Tam aradığım şey. Yerleşik json kütüphanesinin yeniden kullanımı ile kolay güzel baskı.
AmiralThrawn

Alan türünü ve uzunluğunu yazdırmak gerekmedikçe (Spew bunun için harikadır), işaretçiler de düzgün bir şekilde yazdırıldığı için bu çözüm en iyisidir!
Christophe Vidal

Kısa ve tatlı. Sen değiştirebilirsiniz "\t"ile " "Bunun yerine ara girintilemeyi istiyorsanız
Dana Woodman

1
Unutmayın, Marshal()sadece bir yapının dışa aktarılan alanlarını serileştirir - yine de haritalar için mükemmeldir.
nobar

24

Ben biçimlendirilmiş bir çıktı bir tür istiyorsanız özel bir stringer uygulamak daha iyi olacağını düşünüyorum struct

Örneğin

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)Bana atar main.structile struct type arasındaki farkın ne "%#v"ve "%+v"@cokebol
muthukumar Helius

13

Alternatif olarak, bu işlevi kullanmayı deneyin 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)
}

Bunu kullanabilmek için, oluşturduğunuz yapı dışında fmtve encoding/jsonsadece referans, işaretçi veya hazır bilgi haricinde herhangi bir ek pakete ihtiyacınız yoktur .

Kullanmak için sadece yapınızı alın, ana olarak veya içinde bulunduğunuz herhangi bir paketi başlatın ve içine geçirin 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)
}

Çıktısı

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

Buradaki kodla oynayın .


5

Çöpü severim .

Benioku dosyalarından:

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

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

Sdump testlerde oldukça kullanışlıdır:

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

Pretty Printer Library kullanmanızı tavsiye ederim . Böylece herhangi bir yapıyı çok kolay bir şekilde yazdırabilirsiniz.

  1. Kitaplığı Yükle

    https://github.com/kr/pretty

veya

go get github.com/kr/pretty

Şimdi kodunuzda bunu yapın

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.

}

Ayrıca bu kütüphane aracılığıyla bileşen ve daha fazlası arasında fark elde edebilirsiniz. Ayrıca burada Dokümanlar kitaplığına da göz atabilirsiniz .


1
pretty.Formatter
Konstantin Tikhonov

4

Daha karmaşık yapılarınız olduğunda, yazdırmadan önce JSON'a dönüştürmeniz gerekebilir:

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

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


3

Kodun tamamını görmek için burayı ziyaret edin . Burada ayrıca tam kodun çalıştırılabileceği bir çevrimiçi terminal için bir bağlantı bulacaksınız ve program yapının bilgilerinin nasıl çıkarılacağını temsil eder (alanın adı ve değeri). Aşağıda yalnızca alan adlarını yazdıran program snippet'i bulunmaktadır.

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

İşaretçi özyinelemesini ve dize ve int haritaları için çok sayıda anahtar sıralamasını işleyen go-render da vardır .

Kurulum:

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

Misal:

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

Hangi baskılar:

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)

Ayrıntıları yazdırmanın temel yolu budur


0

Başka bir yol, toStringstruct alan adında bir işlev oluşturmak , alanları istediğiniz gibi biçimlendirmektir.

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
Veya Stringerarayüzü uygulayabilirsiniz . Şöyle bir şey olurdu: 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) }
rbo13

0

Harici kütüphaneler kullanmadan ve her alandan sonra yeni satırla:

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

çok basit Veri ve Taahhüt yapısına sahip değilim.

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

Öğrenmek için buradan yardım alabilirsiniz: https://gobyexample.com/structs


0

Belki bu üretim istekleri için uygulanmamalıdır, ancak hata ayıklama modundaysanız aşağıdaki yaklaşımı izlemenizi öneririm.

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

Bu, verilerin okunabilirliği artırılarak json formatında biçimlendirilmesi ile sonuçlanır.



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

Bunu yapmanın daha iyi bir yolu, "commons" (belki) adlı bir pakette "% + v" dizesi için global bir sabit oluşturmak ve kodunuzun her yerinde kullanmaktır.

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

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

3
Politik olarak, insanlar bunu aşağı oyladı çünkü Printlnişlev bir biçim dizesi argümanını kabul etmiyor. Küresel bir sabitin daha iyi olduğunu söylüyorsunuz, ancak neden belirgin yanıttan daha iyi olduğunu haklı göstermediniz. İyi bilinen bir biçim dizesi için standart olmayan bir etiket oluşturdunuz. Etiket çok daha uzun, hatırlanması zor ve kodunuz üzerinde çalışan hiç kimse bunu kullanmaz. Hem ALL_CAPS hem de her golang linterinin şikayet edeceği bir alt çizgi kullanır. Sözleşme mixedCaps golang.org/doc/effective_go.html#mixed-caps Bu yanıtı kaldırmak için muhtemelen en iyisidir.
Davos
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.