Làm thế nào để in các biến struct trong console?


380

Làm thế nào tôi có thể in (trong giao diện điều khiển) các Id, Title, Name, vv của struct này trong 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
Tất cả trong số họ, để gỡ lỗi? Hãy thử fmt.Println.
Ry-

Câu trả lời:


641

Để in tên của các trường trong một cấu trúc:

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

Từ fmtgói :

khi in cấu trúc, cờ cộng ( %+v) thêm tên trường

Điều đó cho rằng bạn có một thể hiện của Dự án (trong ' yourProject')

Bài viết JSON và Go sẽ cung cấp thêm chi tiết về cách truy xuất các giá trị từ cấu trúc JSON.


Đây Go bởi trang ví dụ cung cấp kỹ thuật khác:

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

Điều đó sẽ in:

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

Nếu bạn không có bất kỳ trường hợp nào, thì bạn cần sử dụng sự phản chiếu để hiển thị tên của trường của một cấu trúc nhất định, như trong ví dụ này .

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
Cảm ơn câu trả lời của bạn nhưng có một điều nữa. Các tệp JSON của tôi có liên quan đến API ... do đó tôi không muốn đặt Id hoặc Tên, tôi chỉ muốn lấy nó qua API và in nó trong bảng điều khiển. Làm thế nào tôi có thể làm điều đó?
fnr

4
@fnr Nếu bạn có một tài liệu JSON, bạn sẽ cần phải sắp xếp lại nó, trước khi có thể in trường của nó.
VonC

3
Nâng cao! Một khiếu nại của tôi là lệnh% + v không in đẹp lắm! Tôi vẫn hài lòng với hiệu quả của dòng này.
Shadoninja

1
Cần nhập "mã hóa / json" cho kỹ thuật sắp xếp thứ tự json,
Jim Hoagland

1
Lưu ý rằng .Printf ("% + v \ n") cũng hoạt động với gói "nhật ký"
Ariel Monaco

139

Tôi muốn giới thiệu go-spew , theo github của họ "Triển khai một máy in đẹp sâu cho cấu trúc dữ liệu Go để hỗ trợ gỡ lỗi"

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

ví dụ sử dụng:

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

đầu ra:

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

5
bạn có thể thêm tính năng bổ nhiệm mà go-spew có. Nó cho phép bạn in giá trị của struct nơi con trỏ đang tham chiếu và không phải con trỏ của nó

Các pro lớn với spew sử dụng là đầu ra đã được định dạng tốt để bạn có thể dễ dàng kiểm tra tất cả các thuộc tính đối tượng.
COil

97

2cents của tôi sẽ được sử dụng json.MarshalIndent- thật ngạc nhiên khi điều này không được đề xuất, vì nó đơn giản nhất. ví dụ:

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

không có deps bên ngoài và kết quả trong đầu ra được định dạng độc đáo.


2
Lựa chọn thú vị. +1
VonC

1
Chính xác những gì tôi đang tìm kiếm. Dễ dàng in ấn với tái sử dụng được xây dựng trong thư viện json.
Đô đốcThrawn

Trừ khi người ta cần in loại và độ dài trường (Spew là tuyệt vời cho điều đó), giải pháp này là tốt nhất vì Con trỏ cũng được in đúng cách!
Barshe Vidal

Ngắn và ngọt ngào. Bạn có thể thay thế "\t"bằng " "nếu bạn muốn thụt lề thay thế
Dana Woodman

1
Lưu ý, Marshal()chỉ tuần tự hóa các trường đã xuất của một cấu trúc - mặc dù nó hoàn hảo cho bản đồ.
tộc

24

Tôi nghĩ sẽ tốt hơn nếu thực hiện một stringer tùy chỉnh nếu bạn muốn một số loại đầu ra được định dạng của một struct

ví dụ

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), Ném cho tôi main.structvới struct type sự khác biệt giữa là những gì "%#v""%+v"@cokebol
Helius muthukumar

13

Ngoài ra, hãy thử sử dụng chức năng này 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)
}

Để sử dụng điều này, bạn không cần bất kỳ gói bổ sung nào ngoại trừ fmtencoding/json, chỉ cần một tham chiếu, con trỏ tới hoặc bằng chữ của cấu trúc bạn đã tạo.

Để sử dụng, chỉ cần lấy cấu trúc của bạn, khởi tạo nó trong gói chính hoặc bất kỳ gói nào bạn đang sử dụng và chuyển nó vào 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)
}

Đầu ra của nó sẽ là

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

Chơi xung quanh với mã ở đây .


5

Tôi thích xả rác .

Từ readme của họ:

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

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

Sdump là khá tiện dụng trong các bài kiểm tra:

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

Tôi khuyên bạn nên sử dụng Thư viện máy in đẹp . Trong đó bạn có thể in bất kỳ cấu trúc rất dễ dàng.

  1. Cài đặt thư viện

    https://github.com/kr/pretty

hoặc là

go get github.com/kr/pretty

Bây giờ làm như thế này trong mã của bạ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.

}

Ngoài ra, bạn có thể nhận được sự khác biệt giữa các thành phần thông qua thư viện này và nhiều hơn nữa. Bạn cũng có thể xem thư viện Docs tại đây.


1
Sẽ rất hữu ích khi xem ví dụ về đầu ra được tạo bởipretty.Formatter
Konstantin Tikhonov

4

Khi bạn có các cấu trúc phức tạp hơn, bạn có thể cần phải chuyển đổi sang JSON trước khi in:

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

Nguồn: https://gist.github.com/tetsuok/4942960


3

Chuyến thăm vào đây để xem mã hoàn chỉnh. Tại đây, bạn cũng sẽ tìm thấy một liên kết cho một thiết bị đầu cuối trực tuyến nơi có thể chạy mã hoàn chỉnh và chương trình trình bày cách trích xuất thông tin của cấu trúc (tên trường loại & giá trị của chúng). Dưới đây là đoạn chương trình chỉ in tên trường.

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

Ngoài ra còn có kết xuất , xử lý đệ quy con trỏ và rất nhiều cách sắp xếp khóa cho bản đồ chuỗi và int.

Cài đặt:

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

Thí dụ:

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

Bản in nào:

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)

Đây là cách cơ bản để in các chi tiết


0

Một cách khác là, tạo một func được gọi là toStringstruct, định dạng các trường theo ý muốn.

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
Hoặc bạn có thể thực hiện Stringergiao diện. Nó sẽ trông giống như thế này: 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

Không sử dụng các thư viện bên ngoài và với dòng mới sau mỗi trường:

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

rất đơn giản Tôi không có cấu trúc của Dữ liệu và Cam kết Vì vậy tôi đã thay đổi

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

Để học, bạn có thể nhận trợ giúp từ đây: https://gobyexample.com/structs


0

Có thể điều này không nên được áp dụng cho các yêu cầu sản xuất nhưng nếu bạn đang ở chế độ gỡ lỗi, tôi khuyên bạn nên làm theo cách tiếp cận dưới đây.

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

Điều này dẫn đến việc định dạng dữ liệu ở định dạng json với khả năng đọc dễ dàng hơn.



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

Cách tốt hơn để làm điều này là tạo một hằng số toàn cầu cho chuỗi "% + v" trong gói có tên là "commons" (có thể) và sử dụng nó ở mọi nơi trong mã của bạn

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

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

3
Một cách lịch sự, mọi người đã bỏ phiếu này vì Printlnhàm không chấp nhận đối số chuỗi định dạng. Bạn nói rằng một hằng số toàn cầu là tốt hơn nhưng không thể biện minh được tại sao nó tốt hơn câu trả lời được đánh dấu. Bạn đã tạo nhãn không chuẩn cho chuỗi định dạng nổi tiếng. Nhãn dài hơn, khó nhớ hơn và không ai khác làm việc với mã của bạn sẽ sử dụng nó. Nó sử dụng cả ALL_CAPS và dấu gạch dưới mà mọi kẻ nói dối golang sẽ phàn nàn. Quy ước là mixedCaps golang.org/doc/effective_go.html#mixed-caps Có lẽ tốt nhất để xóa câu trả lời này.
Davos
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.