Распечатать определение структуры из экземпляра в Go - PullRequest
0 голосов
/ 29 октября 2018

Я ищу библиотеку или фрагмент, который позволяет (красиво) печатать не содержимое экземпляра структуры, а его структуру. Вот какой-то код и ожидаемый вывод:

package main

import "fantastic/structpp"

type Foo struct {
    Bar string
    Other int
}

func main() {
    i := Foo{Bar: "This", Other: 1}
    str := structpp.Sprint{i}
    fmt.Println(str)
}

напечатает (это или подобное):

Foo struct {
    Bar string
    Other int
}   

Обратите внимание, что мне известно о github.com/davecgh/go-spew/spew, но я не хочу распечатывать данные, мне нужно только определение структуры.

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Я не вижу другого выбора, кроме как использовать отражение

func Sprint(v interface{}) string {

    t := reflect.Indirect(reflect.ValueOf(v)).Type()

    fieldFmt := ""

    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        fieldFmt += "\t" + field.Name + " " + field.Type.Name() + "\n"
    }

    return "type " + t.Name() + " struct {\n" + fieldFmt + "}"
}

Обратите внимание, что эта функция не имеет проверки / проверки и может вызывать панику из-за неструктурного ввода.

Edit: Игровая площадка Go: https://play.golang.org/p/5RiAt86Wj9F

Какие выходы:

type Foo struct {
    Bar string
    Other int
}
0 голосов
/ 29 октября 2018

Хотелось бы что-нибудь подобное? Может потребоваться некоторая корректировка в зависимости от вашей конкретной структуры и варианта использования (хотите ли вы печатать интерфейсы {}, где значение на самом деле является структурой и т. Д.)

package main

import (
    "fmt"
    "reflect"
)

func printStruct(t interface{}, prefix string) {
    s := reflect.Indirect(reflect.ValueOf(t))
    typeOfT := s.Type()

    for i := 0; i < s.NumField(); i++ {
        f := s.Field(i)

        fmt.Printf("%s%s %s\n", prefix, typeOfT.Field(i).Name, typeOfT.Field(i).Type)
        switch f.Type().Kind() {
        case reflect.Struct, reflect.Ptr:
            fmt.Printf("%s{\n", prefix)
            printStruct(f.Interface(), prefix+"\t")
            fmt.Printf("%s}\n", prefix)

        }
    }
}

Тогда для этой структуры:

type C struct {
    D string
}

type T struct {
    A int
    B string
    C *C
    E interface{}
    F map[string]int
}

t := T{
    A: 23,
    B: "hello_world",
    C: &C{
        D: "pointer",
    },
    E: &C{
        D: "interface",
    },
}

Вы получаете:

A int
B string
C *main.C
{
    D string
}
E interface {}
F map[string]int

Go Playground Link: https://play.golang.org/p/IN8-fCOe0OS

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...