콘솔에서 구조체 변수를 인쇄하는 방법은 무엇입니까?


379

어떻게 (콘솔에서) 인쇄 할 수 있습니다 Id, Title, Name, 등 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-

답변:


639

구조체에서 필드의 이름을 인쇄하려면 :

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

로부터 fmt패키지 :

구조체를 인쇄 할 때 더하기 플래그 ( %+v)는 필드 이름을 추가합니다.

즉, ' yourProject' 의 Project 인스턴스가 있다고 가정합니다.

JSON 및 Go 기사에서는 JSON 구조체에서 값을 검색하는 방법에 대해 자세히 설명합니다.


Go by 예제 페이지 는 다른 기술을 제공합니다.

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
답변 주셔서 감사하지만 하나 더 있습니다. 내 JSON 파일은 API와 관련이 있습니다. 그러므로 ID 또는 이름을 설정하고 싶지 않습니다. API를 통해 가져 와서 콘솔에서 인쇄하고 싶습니다. 어떻게해야합니까?
fnr

4
@fnr JSON 문서가있는 경우 필드를 인쇄하려면 먼저 문서를 언 마샬링해야합니다.
VonC

3
공감! 내 불만은 % + v 명령이 인쇄하지 않는다는 것입니다! 이 라인의 효율성에 여전히 만족합니다.
Shadoninja

1
json 마샬링 기술을 위해 "인코딩 / json"을 가져와야합니다.
Jim Hoagland

1
.Printf ( "% + v \ n")는 "log"패키지와도 작동합니다.
Ariel Monaco

139

github "go 디버깅을 돕기 위해 Go 데이터 구조를위한 깊고 예쁜 프린터 구현"에 따르면 go-spew 를 추천하고 싶습니다.

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
고 스프레이 기능이있는 역 참조 기능을 추가 할 수 있습니다. 포인터가 아닌 포인터가 참조하는 구조체의 값을 인쇄 할 수 있습니다.

널리 사용되는 전문가는 출력이 이미 형식화되어있어 모든 객체 속성을 쉽게 확인할 수 있다는 것입니다.
코일

97

내 2cents는 사용하는 것이 좋을 것 json.MarshalIndent입니다. 이것이 가장 간단하기 때문에 이것이 제안되지 않은 것에 놀랐습니다. 예를 들면 다음과 같습니다.

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

외부 뎁스가 없어서 형식이 좋은 출력물이됩니다.


2
재미있는 옵션. +1
VonC

1
정확히 내가 찾던 것. 내장 된 json 라이브러리를 재사용하여 쉽게 예쁜 인쇄.
AdmiralThrawn

필드 유형과 길이를 인쇄해야하는 경우가 아니면 (스파이가 적합 함)이 솔루션은 포인터도 올바르게 인쇄되므로 최고입니다!
Christophe Vidal

👏🏻 짧고 달콤합니다. 당신은 대체 할 수 "\t"" "대신 공간 들여 쓰기를 원하는 경우
다나 나무꾼에게

1
참고로, Marshal()구조체의 익스포트 된 필드 만 직렬화합니다. 맵에 적합합니다.
nobar

24

형식화 된 출력을 원하는 경우 사용자 지정 stringer를 구현하는 것이 좋습니다. 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)
}

이것을 사용하기 위해 당신은의를 제외하고 추가 패키지를 필요하지 않습니다 fmtencoding/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

포인터 재귀와 문자열 및 int 맵에 대한 많은 키 정렬을 처리하는 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)}

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

세부 사항을 인쇄하는 기본 방법입니다


0

또 다른 방법은 toString구조체를 사용하고 원하는대로 필드를 포맷 하는 펑크를 만듭니다 .

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 형식으로 형식화합니다.



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

이 작업을 수행하는 더 좋은 방법은 "commons"(아마도)라는 패키지에서 문자열 "% + 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와 모든 골랑 린터가 불평 할 밑줄을 모두 사용합니다. 이 규칙은 mixedCaps golang.org/doc/effective_go.html#mixed-caps 입니다.이 답변을 제거하는 것이 가장 좋습니다.
Davos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.