4

I am looking for a lib or snippet that allows to (pretty) print not the content of a struct instance but its structure. Heres a some code and the expected output:

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

would print (this or similar):

Foo struct {
    Bar string
    Other int
}   

Note that I am aware of github.com/davecgh/go-spew/spew but I don't want to prettyprint the data, I only need the definition of the struct.

3
  • Possible duplicate of How to print struct variables in console? Commented Oct 29, 2018 at 7:22
  • No, as mentioned I only want to print the struct definition, not its content. Commented Oct 29, 2018 at 7:24
  • The accepted answer give examples on how to do both. Commented Oct 29, 2018 at 10:39

2 Answers 2

4

Would something like this work? Might need some adjusting depending on your specific struct and use case (whether you want to print interfaces{} where the value is actually a struct, etc.)

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)

        }
    }
}

Then, for this struct:

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",
    },
}

You get:

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

Sign up to request clarification or add additional context in comments.

1 Comment

Thats it, neat!
3

I can see no other option than using reflection

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 + "}"
}

Note though that this function has no validation/checking and might panic for non struct input.

Edit: Go playground: https://play.golang.org/p/5RiAt86Wj9F

Which outputs:

type Foo struct {
    Bar string
    Other int
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.