コンソールで構造体変数を出力する方法は?


380

どのように私は(コンソールで)印刷することができIdTitleName、などGolangで、この構造体の?

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
デバッグ用ですか?お試しくださいfmt.Println
Ry-

回答:


641

構造体のフィールドの名前を出力するには:

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

fmtパッケージから:

構造体を出力するとき、プラスフラグ(%+v)はフィールド名を追加します

( ' yourProject'内に)Projectのインスタンスがあると仮定します

JSONと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())
}

1
回答ありがとうございます。もう1つあります。私のJSONファイルはAPIに関連しています...そのため、IDや名前を設定したくないので、APIを介して取得し、コンソールに出力したいだけです。どうやってやるの?
fnr 2014

4
@fnr JSONドキュメントがある場合、そのフィールドを印刷する前に、アンマーシャルする必要があります。
VonC、2014

3
賛成です!私の1つの不満は、%+ vコマンドがそれをかなり印刷しないことです!このラインの効率にはまだ満足しています。
Shadoninja 2016

1
jsonマーシャリングテクニックのために "encoding / json"をインポートする必要があります
Jim Hoagland

1
.Printf( "%+ v \ n")は "log"パッケージでも機能することに注意してください
Ariel Monaco

139

私は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) ""
}

5
go-spewが持つ間接参照機能を追加できます。これにより、ポインタitelではなく、ポインタが参照している構造体の値を出力できます

use spewの大きな利点は、出力が既に適切にフォーマットされているため、すべてのオブジェクトプロパティを簡単に確認できることです。
コイル

97

私の2セントは使用することになりますjson.MarshalIndent-これが最も簡単なので、これは推奨されていません。例えば:

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

外部の依存関係はなく、適切にフォーマットされた出力になります。


2
興味深いオプション。+1
VonC 2018

1
まさに私が探していたもの。組み込みのjsonライブラリを再利用して、簡単にきれいに印刷できます。
AdmiralThrawn

フィールドのタイプと長さを印刷する必要がない限り(Spewはそのために最適です)、ポインターも適切に印刷されるため、このソリューションが最適です。
Christophe Vidal

👏🏻短くて甘い。あなたは置き換えることができます"\t"" "、あなたがスペースではなく、インデントしたい場合
ダナウッドマン

1
注目すべきMarshal()は、構造体のエクスポートされたフィールドのみをシリアル化することです-ただし、マップには最適です。
nobar

24

ある種のフォーマットされた出力が必要な場合は、カスタムのストリンガーを実装する方が良いと思います 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)
    }

18
p = Project{...}
fmt.Printf("%+v", p)
fmt.Printf("%#v", p) //with type

2
fmt.Printf(%#v, p)、私を投げるmain.structstruct type の違いは何か"%#v""%+v"@cokebol
muthukumar helius

13

または、この関数を使用してみてください 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)
}

これを使用するには、fmtandを除いて、追加のパッケージは必要ありません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
} 

ここでコードをいじってください


5

ごみが好きです。

彼らの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)
  }
}

5

Pretty Printer Libraryの使用をお勧めします。そのため、構造体を非常に簡単に印刷できます。

  1. ライブラリをインストール

    https://github.com/kr/pretty

または

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.

}

また、このライブラリなどを使用して、コンポーネント間の違いを取得できます。ここでライブラリドキュメントを確認することもできます。


1
pretty.Formatter
Konstantin Tikhonov


3

完全なコードを確認するには、ここにアクセスてください。ここには、完全なコードを実行できるオンライン端末へのリンクもあり、プログラムは構造の情報(フィールドの名前、タイプと値)を抽出する方法を表しています。以下は、フィールド名のみを出力するプログラムスニペットです。

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

go-renderもあります。これは、ポインタの再帰と、文字列およびintマップの多くのキーのソートを処理します。

インストール:

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


0

もう1つの方法は、toString構造体をとるfuncを作成し、必要に応じてフィールドをフォーマットすることです。

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
または、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) }
。– rbo13

0

外部ライブラリを使用せずに、各フィールドの後に改行を追加します。

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

非常に単純です。データとコミットの構造を持っていないので、

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からヘルプを利用できます。


0

多分これはプロダクションリクエストに適用すべきではありませんが、デバッグモードの場合は、以下のアプローチに従うことをお勧めします。

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

これにより、読みやすさが向上したjson形式でデータがフォーマットされます。


-2

これらのパッケージのほとんどは、そのようなことを可能にするためにReflectパッケージに依存しています。

ここに画像の説明を入力してください

fmt.Sprintf()が標準ライブラリの-> func(p * pp)printArg(arg interface {}、verb rune)を使用している

638行目に移動-> https://golang.org/src/fmt/print.go

反射:

https://golang.org/pkg/reflect/

コード例:

https://github.com/donutloop/toolkit/blob/master/debugutil/prettysprint.go


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

これを行うためのより良い方法は、「c​​ommons」(たぶん)と呼ばれるパッケージに文字列「%+ v」のグローバル定数を作成し、コード内のあらゆる場所で使用することです

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

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

3
Println関数はフォーマット文字列引数を受け入れないため、丁寧に人々はこれに反対票を投じました。グローバル定数の方が良いとおっしゃっていますが、マークされた回答よりも優れている理由を正当化していません。よく知られたフォーマット文字列に対して非標準のラベルを作成しました。ラベルははるかに長く、覚えるのが難しく、コードで作業する他の誰もそれを使用しません。ALL_CAPSと、すべてのgolangリンターが不平を言うアンダースコアの両方を使用します。規約はmixedCaps golang.org/doc/effective_go.html#mixed-capsです。おそらく、この回答を削除するのが最善です。
ダボス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.