structure: more improvements
5 files changed
tree: 249bd8218ea49640365a189dfc6661cd4d1be852
  1. .gitignore
  2. .travis.yml
  3. field.go
  4. field_test.go
  5. LICENSE
  6. README.md
  7. structure.go
  8. structure_example_test.go
  9. structure_test.go
  10. tags.go
  11. tags_test.go
README.md

Structure GoDoc Build Status Coverage Status

Structure contains various utilities to work with Go (Golang) structs. It was initially used by me to convert a struct into a map[string]interface{}. With time I‘ve added other utilities for structs. It’s basically a high level package based on primitives from the reflect package. Feel free to add new functions or improve the existing code.

Install

go get github.com/fatih/structure

Usage and Examples

Lets define and declare a struct

type Server struct {
	Name        string `json:"name,omitempty"`
	ID          int
	Enabled     bool
	users       []string // not exported
	http.Server          // embedded
}

server := &Server{
	Name:    "gopher",
	ID:      123456,
	Enabled: true,
}

Struct methods

Let's create a new Struct type.

// Create a new struct type:
s := structure.New(server)

// Convert a struct to a map[string]interface{}
// => {"Name":"gopher", "ID":123456, "Enabled":true}
m := s.Map()

// Convert the values of a struct to a []interface{}
// => ["gopher", 123456, true]
v := s.Values()

// Check if any field of a struct is initialized or not.
if s.HasZero() {
    fmt.Println("s has a zero value field")
}

// Check if all fields of a struct is initialized or not.
if s.IsZero() {
    fmt.Println("all fields of s is zero value")
}

// Return the struct name
// => "Server"
n := s.Name()

Most of the struct methods are available as global functions without the need for a New() constructor:

m := structure.Map(s)
v := structure.Values(s)
f := structure.Fields(s)
n := structure.Name(s)

hasZero :=  structure.HasZero(s)
isZero := structure.IsZero(s)

// Check if it's a struct or a pointer to struct
if structure.IsStruct(s) {
    fmt.Println("s is a struct")
}

Field methods

We can easily examine a single Field for more detail. Below you can see how we get and interact with various field methods:

s := structure.New(server)

// Get the Field struct for the "Name" field
name := s.Field("Name")

// Get the underlying value,  value => "gopher"
value := name.Value().(string)

// Check if the field is exported or not
if name.IsExported() {
	fmt.Println("Name field is exported")
}

// Check if the value is a zero value, such as "" for string, 0 for int
if !name.IsZero() {
	fmt.Println("Name is initialized")
}

// Check if the field is an anonymous (embedded) field
if !name.IsEmbedded() {
	fmt.Println("Name is not an embedded field")
}

// Get the Field's tag value for tag name "json", tag value => "name,omitempty"
tagValue := name.Tag("json")

Nested structs are supported too:

addrField := s.Field("Server").Field("Addr")

// Get the value for addr
a := addrField.Value().(string)

We can also get a slice of Fields from the Struct type to iterate over all fields. This is handy if you whish to examine all fields:

// Convert the fields of a struct to a []*Field
fields := s.Fields()

for _, f := range fields {
	fmt.Printf("field name: %+v\n", f.Name())

	if f.IsExported() {
		fmt.Printf("value   : %+v\n", f.Value())
		fmt.Printf("is zero : %+v\n", f.Value())
	}
}

Credits

License

The MIT License (MIT) - see LICENSE.md for more details