structs

package module
v1.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 17, 2022 License: MIT Imports: 12 Imported by: 0

README

Golang structs Go Reference license build coverage

Package structs implements a generic interface for manipulating Go structs. The related API is powered and inspired from the Go reflection package.

Installation

go get github.com/roninzo/structs

Usage

Example

main.go:

package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type T struct {
		String string
		Uint   uint
		Bool   bool
		Int    int32
	}

	t := T{
		String: "Roninzo",
		Uint:   123456,
		Bool:   true,
		Int:    5,
	}

	s, err := structs.New(&t)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
		return
	}

	fmt.Printf("Name               : %v.\n", s.Name())
	fmt.Printf("Value of 1st field : %v.\n", s.Field(0).Value())
	fmt.Printf("Value of Uint      : %v.\n", s.Field("Uint").Value())
	fmt.Printf("Value of Int       : %v.\n", s.Field("Int").Value())
	fmt.Printf("Sprint: %s.\n", s.Sprint())

	err = s.Field("Uint").Set(uint(654321))
	if err != nil {
		fmt.Printf("Set[Error]: %v.\n", err)
	}

	err = s.Field("Int").Set(6)
	if err != nil {
		fmt.Printf("Set[Error]: %v.\n", err)
	}

	err = s.Field("Bool").Set(6)
	if err != nil {
		fmt.Printf("Set[Error]: %v.\n", err)
	}

	fmt.Printf("Value of String    : %s.\n", s.Field("String").String()) // syntax for %s verb
	fmt.Printf("Value of Uint      : %d.\n", s.Field("Uint").Uint())     // syntax for %d verb
	fmt.Printf("Value of Int       : %d.\n", s.Field("Int").Int())       // syntax for %d verb
	fmt.Printf("Sprint: %s.\n", s.Sprint())
	fmt.Printf("\nVerification       :\n")
	fmt.Printf("t.String           : %s.\n", t.String)
	fmt.Printf("t.Uint             : %d.\n", t.Uint)
	fmt.Printf("t.Int              : %d.\n", t.Int)
}
Execute
go run main.go
Output
Name               : T.
Value of 1st field : Roninzo.
Value of Uint      : 123456.
Value of Int       : 5.
Sprint: {
	"String": "Roninzo",
	"Uint": 123456,
	"Bool": true,
	"Int": 5
	}.
Set[Error]: wrong kind of value for field T.Bool. got: 'int' want: 'bool'.
Value of String    : Roninzo.
Value of Uint      : 654321.
Value of Int       : 6.
Sprint: {
	"String": "Roninzo",
	"Uint": 654321,
	"Bool": true,
	"Int": 6
	}.

Verification       :
t.String           : Roninzo.
t.Uint             : 654321.
t.Int              : 6.

Caveat

Package API is not final yet.

Documentation

Dependencies

Inspired/forked from

To Do

  • Extend support for Pointer to struct fields
  • Extend support for Slice of any Type as struct fields
  • Extend support for Map of any Type as struct fields
  • Extend support for Method of struct
  • Extend support for complex64/128 field types
  • Implement Map
  • Improve performance
  • Improve coverage

Documentation

Overview

Package structs implements a generic interface for manipulating Go structs. The related API is powered and inspired from the Go reflection package.

Introduction

It was initially developed to provide generic field getters and setters for any struct. It has grown into an generic abstraction layer to structs powered by the reflect package.

While not being particularly performant compared to other structs packages, it provides a "natural feel" API, convenience, flexibility and simpler alternative compared to using the reflect package directly.

Throughout the documentation, the t variable is assumed to be of type struct T. T has two fields: the first is a string field called "Property" and the second is a nested struct via a pointer called "Nested". While "Property" is set to value "Test", "Number" inside "Nested" is set to 123456.

type T struct{
   Property string
   Nested   *N
}

type N struct{
   Number int
}

t := T{
   Property: "Test",
   Nested:   &N{Number: 123456},
}

NOTE: the same applies to all other variables subsequently declared.

Support

The following input are supported throughout the package:

Types   Description                     Example

T       a struct                        New(t)
*T      a pointer to a struct           New(&t)
[]T     a slice of struct               New([]T{t})
*[]T    a pointer to a slice of struct  New(&[]T{t})
[]*T    a slice of pointers to struct   New([]*T{&t})

NOTE: See the IndirectStruct method for details on the above scenarios.

Implementation

There are two main ways to use for this package to manipulate structs. Either by using the objects and methods or by using helper functions.

Objects and methods: this approach requires calling of the New method first, which gives access to the API of the StructValue, StructField and StructFields objects.

Helper functions: A set of self-contained functions that hides internal implementations powered by the StructValue object, are all declared in the file called helpers.go.

The following table summarizes the above statements:

Usage     Applicable Go Files  Description

Objects   structs.go           StructValue object
          field.go             StructField object
          fields.go            StructFields object
          rows.go              StructRows object

Helpers   helpers.go           Wrapper object functions

All objects in this package are linked to the main StructValue object. The relationships between each one of them are as follow:

 --------------
| *StructValue |<----------------------------------------+
 --+-----------                                          |
   |                                                     |
   |                   ---------------                   |
   +---> Field(x) --->| *StructField  |---> Parent ----->+
   |                   ---------------                   |
   |                                                     |
   |                   ---------------                   |
   +---> Fields() --->| *StructFields |---> Parent() --->+
   |                   ---------------                   |
   |                                                     |
   |                   ---------------                   |
   +---> Rows() ----->| *StructRows   |---> Parent ----->+
                       ---------------

NOTE: For an exhaustive illustration of package capabilities, please refer to the following file: https://github.com/roninzo/structs/example_test.go.

StructValue

The StructValue object is the starting point for manipulating structs using objects and methods. To initialize the StructValue object, make use of the New method followed by handling any potential error encountered in this process.

Example:

s, err := structs.New(&t)
if err != nil {
   return err
}

From there, several methods provides information about the struct.

Example:

fmt.Printf("t has %d field(s)\n", s.NumField())

// Output:
// t has 2 field(s)

NOTE: When possible, all object method names were inspired from the reflect package, trying to reduce the learning curve.

Example:

if s.CanSet() {
   fmt.Println("t is modifiable")
}

// Output:
// t is modifiable

The StructValue object is also the gateway to the other two objects declared in this package: StructField and StructFields.

Examples:

f := s.Field("Property") // f is a StructField object
fields := s.Fields()     // fields is a StructFields object

StructField

The StructField object represents one field in the struct, and provides getters and setters methods.

Before reading data out of struct fields generically, it is recommended to get extra information about the struct field. This is useful if the type of the field is not known at runtime.

Example:

f := s.Field("Property")
if f.CanString() {
   fmt.Printf("Property was equal to %q\n", s.String())
   if f.CanSet() {
      err := f.SetString("Verified")
      if err != nil {
         return err
      }
      fmt.Printf("Property is now equal to %q\n", s.String())
   }
}

// Output:
// Property was equal to 'Test'
// Property is now equal to 'Verified'

However, if nested struct are present inside t, sub-fields are not made available directly. This means that nested structs must be loaded explicitly with the Struct method.

Example:

f := s.Field("Nested")
if err := s.Err(); err != nil {
   return err
}
if f.CanStruct() {
   f = f.Struct().Field("Number")
   if f.CanInt() {
      fmt.Printf("Number was equal to %d\n", f.Int())
      if f.CanSet() {
         err := f.SetInt(654321)
         if err != nil {
            return err
         }
         fmt.Printf("Number is now equal to %d\n", f.Int())
      }
   }
}

// Output:
// Number was equal to 123456
// Number is now equal to 654321

StructFields

The StructFields object represents all the fields in the struct. Its main purpose at the moment, is to loop through StructField objects in a "for range" loop.

Example:

for _, f := range s.Fields() {
   fmt.Printf("struct field name is: %s\n", f.Name())
}

// Output:
// struct field name is: Property
// struct field name is: Nested

The other purpose, is to return all struct filed names:

Example:

names := s.Fields().Names()
fmt.Printf("struct field names are: %v\n", names)

// Output:
// struct field names are: [Property Nested]

StructRows

The StructRows object represents the slice of structs and mostly follows the database/sql API. Its main purpose is to loop through elements of a submitted slice of structs. Each of those elements can then be manipulated in the same manner as the StructValue.

Example:

s, err := structs.New([]*T{&t})
if err != nil {
   return err
}
rows, err := s.Rows()
if err != nil {
   return err
}
defer rows.Close()
for rows.Next() {
   f := rows.Field("Property")
   f.Set(f.String() + "s")        // adds an "s" to the Property field
   fmt.Printf("%s: %s.\n", f.Name(), f.String())
}

// Output:
// Property: Tests.

Helper functions

The helper methods in the helpers.go provide advanced functions for transforming structs or wrap StructValue object functionalities.

Examples:

clone, err := structs.Clone(&t)
if err != nil {
   return err
}
t2, ok := clone.(*T)
if ok {
   same := structs.Compare(t2, &t)
   if same {
      fmt.Println("t and t2 are the same")
   }
   t2.Property = "Cloned"
   if err != nil {
      return err
   }
   same = structs.Compare(t2, &t)
   if !same {
      fmt.Println("t and t2 are now different")
   }
}

// Output:
// t and t2 are the same
// t and t2 are now different

Index

Examples

Constants

View Source
const (
	OutOfRange = -1
	ReplaceAll = -1
)

Variables

View Source
var (
	ErrNotExported = errors.New("struct field is not exported")
	ErrNotSettable = errors.New("struct field is not settable")
	ErrNotNillable = errors.New("struct field is not nillable")
	ErrNoStruct    = errors.New("struct not found")
	ErrNoStructs   = errors.New("structs not found")
	ErrNoField     = errors.New("struct field not found")
	ErrNoFields    = errors.New("struct fields not found")
	ErrNoRow       = errors.New("struct row not found")
	ErrNoRows      = errors.New("struct rows not found")
	ErrRowsClosed  = errors.New("struct rows are closed")
	ErrNotReplaced = errors.New("struct field old and new value types does not match") // could not replace value in struct
)

Functions

func Clone

func Clone(src interface{}) (interface{}, error)

Clone returns a copy from a struct out of nothing.

// ctx will be the context error returned // by this func if anything goes wrong ctx := "could not clone struct" // // Source interface must be valid struct for this to work // Target dest will be the recipient for a copy of src s1, err := New(src)

if err != nil {
	return nil, errors.Wrap(err, ctx)
}

t := s1.Type() dest := reflect.New(t).Interface() s2, err := New(dest)

if err != nil {
	return nil, errors.Wrap(err, ctx)
}

// // ctx content can now now be improved ctx = fmt.Sprintf("could not clone struct %q", s1.Name()) // // Target struct must be editable

if !s2.CanSet() {
	return nil, errors.Wrap(errors.Errorf("cannot edit struct %s", s2.Name()), ctx)
}

// // Target must be singular of struct, not multiple

if s2.Multiple() {
	return nil, errors.Wrap(errors.Errorf("source is a slice of struct %s", s2.Name()), ctx)
}

err = s2.Import(s1) return dest, err

func Compare

func Compare(dest, src interface{}) bool

Compare returns dest boolean comparing two structs.

func Copy

func Copy(dest, src interface{}) error

Copy makes a copy, for instance, of a struct pointer. Do the copy "manually", e.g. create a new struct and copy the fields, where pointers or slices/maps/channels/etc must be duplicated manually, in a recursive manner.

Resources: https://stackoverflow.com/questions/50269322/how-to-copy-struct-and-dereference-all-pointers

// ctx will be the context error returned // by this func if anything goes wrong ctx := "could not copy data between two structs" // // Both interfaces must be valid structs for this to work s1, err := New(src)

if err != nil {
	return errors.Wrap(err, ctx)
}

s2, err := New(dest)

if err != nil {
	return errors.Wrap(err, ctx)
}

// // ctx content can now now be improved ctx = fmt.Sprintf("could not copy data between two %q structs", s1.Name()) // // StructValue names must be the same

if s1.Name() != s2.Name() {
	return errors.Wrap(errors.Errorf("target struct name is invalid: want: %q, got: %q", s1.Name(), s2.Name()), ctx)
}

// // Target struct must be editable

if !s2.CanSet() {
	return errors.Wrap(errors.Errorf("cannot edit struct %s", s2.Name()), ctx)
}

// // Both interfaces must be singulars of struct, not multiples

if s1.Multiple() {
	return errors.Wrap(errors.Errorf("source is a slice of struct %s", s1.Name()), ctx)
}
if s2.Multiple() {
	return errors.Wrap(errors.Errorf("target is a slice of struct %s", s2.Name()), ctx)
}

return s2.Import(s1)

func Defaults added in v1.0.5

func Defaults(dest interface{}) error

Defaults ...

func Diff added in v1.0.3

func Diff(dest, src interface{}) (map[string]interface{}, error)

Diff returns differences between two structs. Where diffs stores values from dest indexed by column names.

func Forward

func Forward(dest, src interface{}) error

Forward copies only non-zero values between two structs, i.e. from src to dest interface.

func MapFunc

func MapFunc(dest interface{}, handler func(reflect.Value) error) (interface{}, error)

MapFunc returns a copy of the StructValue s with all its fields modified according to the mapping function handler.

If mapping returns a negative value, the character is
dropped from the byte slice with no replacement. The characters in s and the
output are interpreted as UTF-8-encoded code points.

BUG(roninzo): the MapFunc method argument dest is also changed. should that be the case?

func Name

func Name(dest interface{}) (string, error)

Name returns the structs's type name within its package. It returns an empty string for unnamed types. It returns an error if s's kind is not struct.

func Names

func Names(dest interface{}) ([]string, error)

Names returns a slice of field names. For more info refer to StructValue types Names() method. It returns an error if s's kind is not struct.

func Replace

func Replace(dest, old, new interface{}, n int) (interface{}, error)

Replace returns a copy of the struct dest with the first n non-overlapping instance of old replaced by new.

Counts how many replacing to do until n. if n = -1, then replace all.

func ScanFromMap added in v1.0.2

func ScanFromMap(dest interface{}, row map[string]interface{}, mapping map[string]string) error

ScanFromMap trusted source maps of string to interface{} row into Go struct dest.

Optionally, a mapping argument can be provided if the column names are different between dest and row. That argument is a key-value pair of strings where key is the column name in dest and value the column name in row.

func Sprint added in v1.0.1

func Sprint(dest interface{}) string

Sprint returns a MarshalIndent string.

BUG(roninzo): Sprint uses json marshaling which does not support complex types (complex64/complex128).

func SprintCompact added in v1.0.3

func SprintCompact(dest interface{}) string

Sprint returns a Marshal one-line string (without indenting).

func Transpose

func Transpose(dest, src interface{}) error

Transpose loops through target fields and set value of its related source field.

func Unmarhsal added in v1.0.5

func Unmarhsal(src interface{}, dest *map[string]interface{}) error

Unmarshal parses the Go struct and stores the result in the value pointed to by dest. If dest is nil or not a pointer, Unmarshal returns an InvalidUnmarshalError.

Types

type StructField

type StructField struct {
	Parent *StructValue // field's own struct reference.
	// contains filtered or unexported fields
}

StructField represents a single struct field that encapsulates high level functions around the field.

func (*StructField) AssignableTo

func (f *StructField) AssignableTo(x reflect.Value) bool

AssignableTo reports whether a field value is assignable to reflect Value x.

NOTE: case utils.CanInterface(v) && utils.CanInterface(x):

no need; x came from interface{} dest

func (*StructField) Bool

func (f *StructField) Bool() bool
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Enabled")

	if f1.CanBool() {
		fmt.Printf("Bool: %v\n", f1.Bool())
	}
	if f2.CanBool() {
		fmt.Printf("Bool: %v\n", f2.Bool())
	}

}
Output:

Bool: true

func (*StructField) Bytes

func (f *StructField) Bytes() []byte
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Stream     []byte `json:"stream,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Stream:     []byte("Hello world"),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Stream")

	if f1.CanBytes() {
		fmt.Printf("Bytes: %v.\n", f1.Bytes())
	}
	if f2.CanBytes() {
		b := f2.Bytes()
		fmt.Printf("Bytes: %v.\n", b)
		fmt.Printf("BytesString: %v.\n", string(b))
	}

}
Output:

Bytes: [72 101 108 108 111 32 119 111 114 108 100].
BytesString: Hello world.

func (*StructField) CanBool

func (f *StructField) CanBool() bool
Example
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string    `json:"name,omitempty"`
		ID         uint      `json:"id,omitempty"`
		Enabled    bool      `json:"enabled,omitempty"`
		ChangedAt  time.Time `json:"changed_at,omitempty"`
		Password   string    `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		ChangedAt:  time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Enabled")

	fmt.Printf("CanBool: %v\n", f1.CanBool())
	fmt.Printf("CanBool: %v\n", f2.CanBool())

}
Output:

CanBool: false
CanBool: true

func (*StructField) CanBytes

func (f *StructField) CanBytes() bool
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Stream     []byte `json:"stream,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Stream:     []byte("Hello world"),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Stream")

	fmt.Printf("CanBytes: %v\n", f1.CanBytes())
	fmt.Printf("CanBytes: %v\n", f2.CanBytes())

}
Output:

CanBytes: false
CanBytes: true

func (*StructField) CanComplex

func (f *StructField) CanComplex() bool
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string     `json:"name,omitempty"`
		ID         uint       `json:"id,omitempty"`
		Enabled    bool       `json:"enabled,omitempty"`
		Complex    complex128 `json:"complex,omitempty"`
		Password   string     `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Complex:    complex(23, 31),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Complex")

	fmt.Printf("CanComplex: %v\n", f1.CanComplex())
	fmt.Printf("CanComplex: %v\n", f2.CanComplex())

}
Output:

CanComplex: false
CanComplex: true

func (*StructField) CanDuration

func (f *StructField) CanDuration() bool
Example
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string        `json:"name,omitempty"`
		ID         uint          `json:"id,omitempty"`
		Enabled    bool          `json:"enabled,omitempty"`
		TimeOut    time.Duration `json:"time_out,omitempty"`
		Password   string        `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		TimeOut:    5 * time.Second,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("TimeOut")

	fmt.Printf("CanDuration: %v\n", f1.CanDuration())
	fmt.Printf("CanDuration: %v\n", f2.CanDuration())

}
Output:

CanDuration: false
CanDuration: true

func (*StructField) CanError

func (f *StructField) CanError() bool
Example
package main

import (
	"fmt"

	"github.com/pkg/errors"
	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Err        error  `json:"err,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Err:        errors.New("failed"),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Err")

	fmt.Printf("CanError: %v\n", f1.CanError())
	fmt.Printf("CanError: %v\n", f2.CanError())

}
Output:

CanError: false
CanError: true

func (*StructField) CanFloat

func (f *StructField) CanFloat() bool
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string  `json:"name,omitempty"`
		ID         uint    `json:"id,omitempty"`
		Enabled    bool    `json:"enabled,omitempty"`
		Price      float32 `json:"price,omitempty"`
		Password   string  `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Price:      10.50,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Price")

	fmt.Printf("CanFloat: %v\n", f1.CanFloat())
	fmt.Printf("CanFloat: %v\n", f2.CanFloat())

}
Output:

CanFloat: false
CanFloat: true

func (*StructField) CanInt

func (f *StructField) CanInt() bool
Example
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string    `json:"name,omitempty"`
		ID         int       `json:"id,omitempty"`
		Enabled    bool      `json:"enabled,omitempty"`
		ChangedAt  time.Time `json:"changed_at,omitempty"`
		Password   string    `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		ChangedAt:  time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("ID")

	fmt.Printf("CanInt: %v\n", f1.CanInt())
	fmt.Printf("CanInt: %v\n", f2.CanInt())

}
Output:

CanInt: false
CanInt: true

func (*StructField) CanInterface

func (f *StructField) CanInterface() bool
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string      `json:"name,omitempty"`
		ID         uint        `json:"id,omitempty"`
		Enabled    bool        `json:"enabled,omitempty"`
		Anything   interface{} `json:"anything,omitempty"`
		Password   string      `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Anything:   654321,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Anything")

	fmt.Printf("CanInterface: %v\n", f1.CanInterface())
	fmt.Printf("CanInterface: %v\n", f2.CanInterface())

}
Output:

CanInterface: false
CanInterface: true

func (*StructField) CanMap added in v1.0.5

func (f *StructField) CanMap() bool

func (*StructField) CanNil

func (f *StructField) CanNil() bool

func (*StructField) CanPtr

func (f *StructField) CanPtr() bool

func (*StructField) CanSet

func (f *StructField) CanSet() bool

Interface returns true if underlying value of the field is modifiable.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name     string  `json:"name,omitempty"`
		ID       uint    `json:"id,omitempty"`
		Enabled  bool    `json:"enabled,omitempty"`
		Count    int32   `json:"count,omitempty"`
		Password string  `json:"-"`
		Program  Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  program,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field(0)

	fmt.Printf("CanSet: %v\n", f.CanSet())

	s, err = structs.New(server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f = s.Field(0)

	fmt.Printf("CanSet: %v\n", f.CanSet())

}
Output:

CanSet: true
CanSet: false

func (*StructField) CanSlice added in v1.0.5

func (f *StructField) CanSlice() bool

func (*StructField) CanString

func (f *StructField) CanString() bool
Example
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string    `json:"name,omitempty"`
		ID         uint      `json:"id,omitempty"`
		Enabled    bool      `json:"enabled,omitempty"`
		ChangedAt  time.Time `json:"changed_at,omitempty"`
		Password   string    `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		ChangedAt:  time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("ChangedAt")

	fmt.Printf("CanString: %v\n", f1.CanString())
	fmt.Printf("CanString: %v\n", f2.CanString())

}
Output:

CanString: true
CanString: false

func (*StructField) CanStruct

func (f *StructField) CanStruct() bool
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name     string  `json:"name,omitempty"`
		ID       uint    `json:"id,omitempty"`
		Enabled  bool    `json:"enabled,omitempty"`
		Count    int32   `json:"count,omitempty"`
		Password string  `json:"-"`
		Program  Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  program,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Program")

	fmt.Printf("CanStruct: %v\n", f1.CanStruct())
	fmt.Printf("CanStruct: %v\n", f2.CanStruct())

}
Output:

CanStruct: false
CanStruct: true

func (*StructField) CanTime

func (f *StructField) CanTime() bool
Example
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string    `json:"name,omitempty"`
		ID         uint      `json:"id,omitempty"`
		Enabled    bool      `json:"enabled,omitempty"`
		ChangedAt  time.Time `json:"changed_at,omitempty"`
		Password   string    `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		ChangedAt:  time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("ChangedAt")

	fmt.Printf("CanTime: %v\n", f1.CanTime())
	fmt.Printf("CanTime: %v\n", f2.CanTime())

}
Output:

CanTime: false
CanTime: true

func (*StructField) CanUint

func (f *StructField) CanUint() bool
Example
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string    `json:"name,omitempty"`
		ID         uint      `json:"id,omitempty"`
		Enabled    bool      `json:"enabled,omitempty"`
		ChangedAt  time.Time `json:"changed_at,omitempty"`
		Password   string    `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		ChangedAt:  time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("ID")

	fmt.Printf("CanUint: %v\n", f1.CanUint())
	fmt.Printf("CanUint: %v\n", f2.CanUint())

}
Output:

CanUint: false
CanUint: true

func (*StructField) Complex

func (f *StructField) Complex() complex128
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string     `json:"name,omitempty"`
		ID         uint       `json:"id,omitempty"`
		Enabled    bool       `json:"enabled,omitempty"`
		Complex    complex128 `json:"complex,omitempty"`
		Password   string     `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Complex:    complex(22, 50),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Complex")

	if f1.CanComplex() {
		fmt.Printf("Complex: %v.\n", f1.Complex())
	}
	if f2.CanComplex() {
		fmt.Printf("Complex: %v.\n", f2.Complex())
	}

}
Output:

Complex: (22+50i).

func (*StructField) Default added in v1.0.4

func (f *StructField) Default() string

Default returns returns the string default value of StructField defined in its related default struct tag, else returns empty string.

func (*StructField) Duration

func (f *StructField) Duration() time.Duration
Example
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string        `json:"name,omitempty"`
		ID         uint          `json:"id,omitempty"`
		Enabled    bool          `json:"enabled,omitempty"`
		TimeOut    time.Duration `json:"time_out,omitempty"`
		Password   string        `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		TimeOut:    5 * time.Second,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("TimeOut")

	if f1.CanDuration() {
		fmt.Printf("Duration: %v\n", f1.Duration())
	}
	if f2.CanDuration() {
		fmt.Printf("Duration: %v\n", f2.Duration())
	}

}
Output:

Duration: 5s

func (*StructField) Equal

func (f *StructField) Equal(x *StructField) bool

Equal compares field value with reflect value argument and returns true

Example
package main

import (
	"fmt"
	"time"

	"github.com/pkg/errors"
	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	program1 := Program{Name: "Apache"}
	program2 := Program{Name: "Apache"}

	type Server struct {
		Name       string        `json:"name,omitempty"`
		ID         uint          `json:"id,omitempty"`
		Enabled    bool          `json:"enabled,omitempty"`
		Err        error         `json:"err,omitempty"`
		ChangedAt  time.Time     `json:"changed_at,omitempty"`
		TimeOut    time.Duration `json:"time_out,omitempty"`
		Count      int           `json:"count,omitempty"`
		Price      float32       `json:"price,omitempty"`
		Complex    complex128    `json:"complex,omitempty"`
		Stream     []byte        `json:"stream,omitempty"`
		Anything   interface{}   `json:"anything,omitempty"`
		Program    *Program      `json:"program,omitempty"`
		Password   string        `json:"-"`
		unexported bool
	}

	server1 := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Err:        errors.New("rows not found"),
		ChangedAt:  time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
		TimeOut:    5 * time.Second,
		Count:      8,
		Price:      1922.50,
		Complex:    complex(22, 50),
		Stream:     []byte("Hello world"),
		Anything:   654321,
		Program:    &program1,
		Password:   "abcdefg",
		unexported: true,
	}

	server2 := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Err:        errors.New("rows not found"),
		ChangedAt:  time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
		TimeOut:    5 * time.Second,
		Count:      8,
		Price:      1922.50,
		Complex:    complex(22, 50),
		Stream:     []byte("Hello world"),
		Anything:   654321,
		Program:    &program2,
		Password:   "abcdefg",
		unexported: true,
	}

	s1, err := structs.New(&server1)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	s2, err := structs.New(&server2)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	for i, f1 := range s1.Fields() {
		f2 := s2.Field(i)
		fmt.Printf("Equal: %v.\n", f1.Equal(f2))
	}

}
Output:

Equal: true.
Equal: true.
Equal: true.
Equal: true.
Equal: true.
Equal: true.
Equal: true.
Equal: true.
Equal: true.
Equal: true.
Equal: true.
Equal: true.
Equal: true.
Equal: false.
Example (Different)
package main

import (
	"fmt"
	"time"

	"github.com/pkg/errors"
	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	program1 := Program{Name: "Apache"}
	program2 := Program{Name: "Microsoft IIS"}

	type Server struct {
		Name       string        `json:"name,omitempty"`
		ID         uint          `json:"id,omitempty"`
		Enabled    bool          `json:"enabled,omitempty"`
		Err        error         `json:"err,omitempty"`
		ChangedAt  time.Time     `json:"changed_at,omitempty"`
		TimeOut    time.Duration `json:"time_out,omitempty"`
		Count      int           `json:"count,omitempty"`
		Price      float32       `json:"price,omitempty"`
		Complex    complex128    `json:"complex,omitempty"`
		Stream     []byte        `json:"stream,omitempty"`
		Anything   interface{}   `json:"anything,omitempty"`
		Program    *Program      `json:"program,omitempty"`
		Password   string        `json:"-"`
		unexported bool
	}

	server1 := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Err:        errors.New("rows not found"),
		ChangedAt:  time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
		TimeOut:    5 * time.Second,
		Count:      8,
		Price:      1922.50,
		Complex:    complex(22, 50),
		Stream:     []byte("Hello world"),
		Anything:   654321,
		Program:    &program1,
		Password:   "abcdefg",
		unexported: true,
	}

	server2 := Server{
		Name:       "ozninoR",
		ID:         654321,
		Enabled:    false,
		Err:        errors.New("not compliant"),
		ChangedAt:  time.Date(2021, time.August, 31, 14, 11, 11, 0, time.UTC),
		TimeOut:    30 * time.Second,
		Count:      3,
		Price:      7622.50,
		Complex:    complex(-67, -42),
		Stream:     []byte("Bye bye world"),
		Anything:   123456,
		Program:    &program2,
		Password:   "gfedcba",
		unexported: false,
	}

	s1, err := structs.New(&server1)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	s2, err := structs.New(&server2)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	for i, f1 := range s1.Fields() {
		f2 := s2.Field(i)
		fmt.Printf("Equal: %v.\n", f1.Equal(f2))
	}

}
Output:

Equal: false.
Equal: false.
Equal: false.
Equal: false.
Equal: false.
Equal: false.
Equal: false.
Equal: false.
Equal: false.
Equal: false.
Equal: false.
Equal: false.
Equal: false.
Equal: false.
Example (PointerFields)
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/pointers"
	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name *string `json:"name,omitempty"`
	}

	type Server struct {
		Name       *string        `json:"name,omitempty"`
		ID         *uint          `json:"id,omitempty"`
		Enabled    *bool          `json:"enabled,omitempty"`
		Err        *string        `json:"err,omitempty"`        // *error
		ChangedAt  *time.Time     `json:"changed_at,omitempty"` // FIXME: should not be different from clone
		TimeOut    *time.Duration `json:"time_out,omitempty"`
		Count      *int           `json:"count,omitempty"`
		Price      *float32       `json:"price,omitempty"`
		Stream     *[]byte        `json:"stream,omitempty"`
		Complex    *complex128    `json:"complex,omitempty"`
		Anything   interface{}    `json:"anything,omitempty"`
		Program    *Program       `json:"program,omitempty"`
		Password   *string        `json:"-"`
		unexported *bool
	}

	program1 := Program{
		Name: pointers.String("Apache"),
	}

	server1 := Server{
		Name:       pointers.String("Roninzo"),
		ID:         pointers.Uint(123456),
		Enabled:    pointers.Bool(true),
		Err:        pointers.String("rows not found"), // pointers.Error(errors.New("rows not found")),
		ChangedAt:  pointers.Time(time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC)),
		TimeOut:    pointers.Duration(5 * time.Second),
		Count:      pointers.Int(8),
		Price:      pointers.Float32(1922.50),
		Stream:     pointers.Bytes([]byte("Hello world")),
		Complex:    pointers.Complex128(complex(22, 50)),
		Anything:   "test",
		Program:    &program1,
		Password:   pointers.String("abcdefg"),
		unexported: pointers.Bool(true),
	}

	program2 := Program{
		Name: pointers.String("Microsoft IIS"),
	}

	server2 := Server{
		Name:       pointers.String("ozninoR"),
		ID:         pointers.Uint(654321),
		Enabled:    pointers.Bool(false),
		Err:        pointers.String("not compliant"), // pointers.Error(errors.New("not compliant")),
		ChangedAt:  pointers.Time(time.Date(2021, time.August, 31, 14, 11, 11, 0, time.UTC)),
		TimeOut:    pointers.Duration(30 * time.Second),
		Count:      pointers.Int(3),
		Price:      pointers.Float32(7022.50),
		Stream:     pointers.Bytes([]byte("Bye bye world")),
		Complex:    pointers.Complex128(complex(99, 12)),
		Anything:   654321,
		Program:    &program2,
		Password:   pointers.String("gfedcba"),
		unexported: pointers.Bool(false),
	}

	// backup <- server1 via cloning
	clone, err := structs.Clone(&server1)
	if err != nil {
		fmt.Printf("Clone[Error]: %v.\n", err)
		return
	}
	backup, ok := clone.(*Server)
	if !ok {
		fmt.Printf("TypeAssertion[Error]: %v.\n", err)
		return
	}

	s1, err := structs.New(&server1)
	if err != nil {
		fmt.Printf("New1[Error]: %v.\n", err)
		return
	}

	s2, err := structs.New(backup)
	if err != nil {
		fmt.Printf("New2[Error]: %v.\n", err)
		return
	}

	fmt.Println("Compare server1 and backup (equal)")
	for i, f1 := range s1.Fields() {
		f2 := s2.Field(i)
		fmt.Printf("[%d]Equal: %v. (%s)\n", i, f1.Equal(f2), f2.Name())
	}

	s2, err = structs.New(&server2)
	if err != nil {
		fmt.Printf("New3[Error]: %v.\n", err)
		return
	}

	fmt.Println("Compare server1 and server2 (different)")
	for i, f1 := range s1.Fields() {
		f2 := s2.Field(i)
		fmt.Printf("[%d]Equal: %v. (%s)\n", i, f1.Equal(f2), f2.Name())
	}

}
Output:

Compare server1 and backup (equal)
[0]Equal: true. (Name)
[1]Equal: true. (ID)
[2]Equal: true. (Enabled)
[3]Equal: true. (Err)
[4]Equal: false. (ChangedAt)
[5]Equal: true. (TimeOut)
[6]Equal: true. (Count)
[7]Equal: true. (Price)
[8]Equal: true. (Stream)
[9]Equal: true. (Complex)
[10]Equal: true. (Anything)
[11]Equal: true. (Program)
[12]Equal: true. (Password)
[13]Equal: false. (unexported)
Compare server1 and server2 (different)
[0]Equal: false. (Name)
[1]Equal: false. (ID)
[2]Equal: false. (Enabled)
[3]Equal: false. (Err)
[4]Equal: false. (ChangedAt)
[5]Equal: false. (TimeOut)
[6]Equal: false. (Count)
[7]Equal: false. (Price)
[8]Equal: false. (Stream)
[9]Equal: false. (Complex)
[10]Equal: false. (Anything)
[11]Equal: false. (Program)
[12]Equal: false. (Password)
[13]Equal: false. (unexported)

func (*StructField) Error

func (f *StructField) Error() error
Example
package main

import (
	"fmt"

	"github.com/pkg/errors"
	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Err        error  `json:"err,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Err:        errors.New("failed"),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Err")

	if f1.CanError() {
		fmt.Printf("Error: %v\n", f1.Error())
	}
	if f2.CanError() {
		fmt.Printf("Error: %v\n", f2.Error())
	}

}
Output:

Error: failed

func (*StructField) Float

func (f *StructField) Float() float64
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string  `json:"name,omitempty"`
		ID         uint    `json:"id,omitempty"`
		Enabled    bool    `json:"enabled,omitempty"`
		Price      float32 `json:"price,omitempty"`
		Password   string  `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Price:      22.50,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Price")

	if f1.CanFloat() {
		fmt.Printf("Float: %v\n", f1.Float())
	}
	if f2.CanFloat() {
		fmt.Printf("Float: %v\n", f2.Float())
	}

}
Output:

Float: 22.5

func (*StructField) FullName added in v1.0.5

func (f *StructField) FullName() (n string)

FullName is similar to the Name method, except that it includes its related struct names all the way to the top level struct (in a dot separated string).

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name     string   `json:"name,omitempty"`
		ID       uint     `json:"id,omitempty"`
		Enabled  bool     `json:"enabled,omitempty"`
		Count    int32    `json:"count,omitempty"`
		Password string   `json:"-"`
		Program  *Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  &program,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.FindStruct("Program").Field(0)

	fmt.Printf("FullName: %v\n", f1.FullName())
	fmt.Printf("FullName: %v\n", f2.FullName())

}
Output:

FullName: Server.Name
FullName: Server.Program.Name

func (*StructField) Get

func (f *StructField) Get() interface{}

Get returns the value of the field as interface. reflect.Struct, reflect.Slice, reflect.Array, reflect.Map, reflect.Interface, reflect.Func, reflect.Chan, reflect.Uintptr, reflect.UnsafePointer, reflect.Invalid Unexported struct fields will be neglected.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Count")
	f3 := s.Field("unexported")
	f4 := s.Field("Password")
	f5 := s.Field("Undeclared")

	err = s.Err()
	if f5 == nil && err != nil {
		fmt.Printf("Error: %v.\n", err)
	}

	v1 := f1.Get()
	v2 := f2.Get()
	v3 := f3.Get()
	v4 := f4.Get()

	fmt.Printf("Value %-11s: %v.\n", f1.Name(), f1.Value())
	fmt.Printf("Value %-11s: %v.\n", f2.Name(), f2.Value())
	fmt.Printf("Value %-11s: %v.\n", f3.Name(), f3.Value())
	fmt.Printf("Value %-11s: %v.\n", f4.Name(), f4.Value())
	fmt.Printf("Get   %-11s: %v.\n", f1.Name(), v1)
	fmt.Printf("Get   %-11s: %v.\n", f2.Name(), v2)
	fmt.Printf("Get   %-11s: %v.\n", f3.Name(), v3)
	fmt.Printf("Get   %-11s: %v.\n", f4.Name(), v4)

}
Output:

Error: invalid field name Undeclared.
Value Name       : Roninzo.
Value Count      : 0.
Value unexported : false.
Value Password   : abcdefg.
Get   Name       : Roninzo.
Get   Count      : 0.
Get   unexported : <nil>.
Get   Password   : abcdefg.

func (*StructField) Index

func (f *StructField) Index() int

Index returns the struct index of the given field. If field is not valid, Index returns the OutOfRange constant, i.e. -1.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Count")

	fmt.Printf("Index: %v\n", f1.Index())
	fmt.Printf("Index: %v\n", f2.Index())

}
Output:

Index: 0
Index: 3

func (*StructField) Indirect added in v1.0.5

func (f *StructField) Indirect() reflect.Value

Indirect returns the value that StructField f.value points to. If f.value is a nil pointer, Indirect returns a zero Value. If f.value is not a pointer, Indirect returns f.value.

Example
package main

import (
	"fmt"

	"github.com/roninzo/pointers"
	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name    *string `json:"name"`
		ID      *uint   `json:"id"`
		Enabled *bool   `json:"enabled"`
		Count   *int32  `json:"count"`
	}

	server := Server{
		Name:    pointers.String("Roninzo"),
		ID:      pointers.Uint(uint(123456)),
		Enabled: pointers.Bool(true),
		Count:   pointers.Int32(int32(5)),
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error          : %v\n", err)
	}

	fmt.Printf("Name           : %v\n", s.Name())
	fmt.Printf("Value of ID    : %v\n", s.Field("ID").Indirect())
	fmt.Printf("Value of 0     : %v\n", s.Field(0).Indirect())
	fmt.Printf("Value of Count : %v\n", s.Field("Count").Indirect())
	fmt.Printf("Sprint: %s.\n", s.Sprint())

	err = s.Field("ID").Set(pointers.Uint(uint(654321)))
	if err != nil {
		fmt.Printf("Error          : %v\n", err)
	}

	err = s.Field("Count").Set(pointers.Int32(int32(6)))
	if err != nil {
		fmt.Printf("Error          : %v\n", err)
	}

	err = s.Field("Enabled").Set(pointers.Int32(int32(6))) // not compatible with bool
	if err != nil {
		fmt.Printf("Error          : %v\n", err)
	}

	fmt.Printf("Value of Name  : %v\n", s.Field("Name").Indirect())
	fmt.Printf("Value of ID    : %v\n", s.Field("ID").Indirect())
	fmt.Printf("Value of Count : %v\n", s.Field("Count").Indirect())
	fmt.Printf("Sprint: %s.\n", s.Sprint())
	fmt.Printf("\nVerification   :\n")
	fmt.Printf("server.Name    : %s\n", *server.Name)
	fmt.Printf("server.ID      : %d\n", *server.ID)
	fmt.Printf("server.Count   : %d\n", *server.Count)

}
Output:

Name           : Server
Value of ID    : 123456
Value of 0     : Roninzo
Value of Count : 5
Sprint: {
 	"name": "Roninzo",
 	"id": 123456,
 	"enabled": true,
 	"count": 5
 }.
Error          : wrong kind of value for field Server.Enabled. got: "*int32" want: "*bool"
Value of Name  : Roninzo
Value of ID    : 654321
Value of Count : 6
Sprint: {
 	"name": "Roninzo",
 	"id": 654321,
 	"enabled": true,
 	"count": 6
 }.

Verification   :
server.Name    : Roninzo
server.ID      : 654321
server.Count   : 6

func (*StructField) IndirectType added in v1.0.5

func (f *StructField) IndirectType() reflect.Type

IndirectType returns the type that field f points to. If f is a pointer, IndirectType returns the type f points to. If f is not a pointer, IndirectType returns the type of f.

func (*StructField) Int

func (f *StructField) Int() int64
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         int    `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("ID")

	if f1.CanInt() {
		fmt.Printf("Int: %v\n", f1.Int())
	}
	if f2.CanInt() {
		fmt.Printf("Int: %v\n", f2.Int())
	}

}
Output:

Int: 123456

func (*StructField) Interface

func (f *StructField) Interface() interface{}
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string      `json:"name,omitempty"`
		ID         uint        `json:"id,omitempty"`
		Enabled    bool        `json:"enabled,omitempty"`
		Anything   interface{} `json:"anything,omitempty"`
		Password   string      `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Anything:   654321,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Anything")

	if f1.CanInterface() {
		fmt.Printf("Interface: %v.\n", f1.Interface())
	}
	if f2.CanInterface() {
		fmt.Printf("Interface: %v.\n", f2.Interface())
	}

}
Output:

Interface: 654321.

func (*StructField) IsAnonymous

func (f *StructField) IsAnonymous() bool

IsAnonymous returns true if the given field is an anonymous field, meaning a field having no name. This obviously related to the use of the Name method.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type T3 struct {
		Config string `json:"config,omitempty"`
	}

	type T2 struct {
		Options string `json:"options,omitempty"`
		T3
	}

	type T1 struct {
		Name     string `json:"name,omitempty"`
		ID       uint   `json:"id,omitempty"`
		Enabled  bool   `json:"enabled,omitempty"`
		Count    int32  `json:"count,omitempty"`
		Password string `json:"-"`
		Nested   T2     `json:"t2,omitempty"`
	}

	t := T1{
		"Roninzo",
		123456,
		true,
		0,
		"abcdefg",
		T2{"654321", T3{"cfg"}},
	}

	s, err := structs.New(&t)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Password")
	f3 := s.Field("Nested").Struct().Field(0)

	fmt.Printf("IsAnonymous: %v\n", f1.IsAnonymous())
	fmt.Printf("IsAnonymous: %v\n", f2.IsAnonymous())
	fmt.Printf("IsAnonymous: %v\n", f3.IsAnonymous())

}
Output:

IsAnonymous: false
IsAnonymous: false
IsAnonymous: false

func (*StructField) IsEmbedded

func (f *StructField) IsEmbedded() bool

IsEmbedded is a alias to the IsAnonymous method. An embedded field can be an anonymous nested struct field.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type T3 struct {
		Config string `json:"config,omitempty"`
	}

	type T2 struct {
		Options string `json:"options,omitempty"`
		T3
	}

	type T1 struct {
		Name     string `json:"name,omitempty"`
		ID       uint   `json:"id,omitempty"`
		Enabled  bool   `json:"enabled,omitempty"`
		Count    int32  `json:"count,omitempty"`
		Password string `json:"-"`
		Nested   T2     `json:"t2,omitempty"`
	}

	t := T1{
		"Roninzo",
		123456,
		true,
		0,
		"abcdefg",
		T2{"654321", T3{"cfg"}},
	}

	s, err := structs.New(&t)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Password")
	f3 := s.Field("Nested").Struct().Field(0)

	fmt.Printf("IsEmbedded: %v\n", f1.IsEmbedded())
	fmt.Printf("IsEmbedded: %v\n", f2.IsEmbedded())
	fmt.Printf("IsEmbedded: %v\n", f3.IsEmbedded())

}
Output:

IsEmbedded: false
IsEmbedded: false
IsEmbedded: false

func (*StructField) IsExported

func (f *StructField) IsExported() bool

IsExported returns true if the given field is exported and its json tag is not equal to "-". Those fields are neglected for getter and setter methods.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("IsExported: %v\n", s.Field(0).IsExported())
	fmt.Printf("IsExported: %v\n", s.Field("Password").IsExported())
	fmt.Printf("IsExported: %v\n", s.Field("unexported").IsExported())

}
Output:

IsExported: true
IsExported: true
IsExported: false

func (*StructField) IsHidden

func (f *StructField) IsHidden() bool

IsHidden returns true if the given field is exported and its json tag is not equal to "-". Those fields are neglected for getter and setter methods.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("IsHidden: %v\n", s.Field(0).IsHidden())
	fmt.Printf("IsHidden: %v\n", s.Field("Password").IsHidden())
	fmt.Printf("IsHidden: %v\n", s.Field("unexported").IsHidden())

}
Output:

IsHidden: false
IsHidden: true
IsHidden: false

func (*StructField) IsNil

func (f *StructField) IsNil() bool

IsNil reports whether its argument f is nil. The argument must be a chan, func, interface, map, pointer, or slice value; if it is not, IsNil returns nil. Unexported struct fields will be neglected.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string  `json:"name,omitempty"`
		ID         *uint   `json:"id,omitempty"`
		Enabled    bool    `json:"enabled,omitempty"`
		Count      *int32  `json:"count,omitempty"`
		Password   *string `json:"-"`
		unexported bool
	}

	var id uint = 5
	server := Server{
		Name:       "Roninzo",
		ID:         &id,
		Enabled:    true,
		Count:      nil,
		Password:   nil,
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("ID")
	f3 := s.Field("Count")
	f4 := s.Field("Password")

	fmt.Printf("IsNil: %v\n", f1.IsNil())
	fmt.Printf("IsNil: %v\n", f2.IsNil())
	fmt.Printf("IsNil: %v\n", f3.IsNil())
	fmt.Printf("IsNil: %v\n", f4.IsNil())

}
Output:

IsNil: false
IsNil: false
IsNil: true
IsNil: true

func (*StructField) IsValid

func (f *StructField) IsValid() bool

IsValid returns true if StructField has been loaded successfully. Useful for checking StructField is valid before use.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := &structs.StructField{}

	fmt.Printf("IsValid: %v\n", f1.IsValid())
	fmt.Printf("IsValid: %v\n", f2.IsValid())

}
Output:

IsValid: true
IsValid: false

func (*StructField) IsZero

func (f *StructField) IsZero() bool

IsZero returns true if the given field is a zero-value, i.e. not initialized. Unexported struct fields will be neglected.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Count")

	fmt.Printf("IsZero: %v\n", f1.IsZero())
	fmt.Printf("IsZero: %v\n", f2.IsZero())

}
Output:

IsZero: false
IsZero: true

func (*StructField) Kind

func (f *StructField) Kind() reflect.Kind

Kind returns the fields kind, such as "string", "int", "bool", etc ..

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Enabled")

	fmt.Printf("Kind: %v\n", f1.Kind())
	fmt.Printf("Kind: %v\n", f2.Kind())

}
Output:

Kind: string
Kind: bool

func (*StructField) Name

func (f *StructField) Name() string

Name returns returns the name of StructField, unless it was invalid. In which case, Name returns zero-value string.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Enabled")

	fmt.Printf("Field: %v\n", f1.Name())
	fmt.Printf("Field: %v\n", f2.Name())

}
Output:

Field: Name
Field: Enabled

func (*StructField) NameJson added in v1.0.5

func (f *StructField) NameJson() string

NameJson returns returns the string name of StructField defined in its related json struct tag, else it generates it.

func (*StructField) Set

func (f *StructField) Set(dest interface{}) error

Set sets the field to a given value dest. It returns an error if the field is not settable (not addressable or not exported) or if the given value's type doesn't match the fields type.

The are not expected for field ...

It has already been established that x is not nil by bailing out on the 'dest == nil' condition above.

  • date <- date date <- text
  • duration <- duration duration <- text duration <- number
  • error <- error error <- text
  • text <- text text <- bool text <- number text <- []byte text <- date
  • bool <- bool bool <- text bool <- number
  • number <- number number <- bool number <- float (losing decimal point value)
  • float <- float float <- number
  • []byte <- []byte []byte <- text
  • complex <- complex

NOTE: Set might benefit from using reflect.Type.AssignableTo() or ConvertibleTo().

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Count")
	f3 := s.Field("unexported")

	fmt.Printf("Value: %v.\n", f1.Value())
	fmt.Printf("Value: %v.\n", f2.Value())
	fmt.Printf("Value: %v.\n", f3.Value())

	err1 := f1.Set("Unknown")
	err2 := f2.Set(10)
	err3 := f3.Set(false)

	fmt.Printf("Value: %v.\n", f1.Value())
	fmt.Printf("Value: %v.\n", f2.Value())
	fmt.Printf("Value: %v.\n", f3.Value())
	fmt.Printf("Error: %v.\n", err1)
	fmt.Printf("Error: %v.\n", err2)
	fmt.Printf("Error: %v.\n", err3)

}
Output:

Value: Roninzo.
Value: 0.
Value: false.
Value: Unknown.
Value: 10.
Value: false.
Error: <nil>.
Error: <nil>.
Error: could not set field Server.unexported: struct field is not settable.
Example (ValueToNil)
package main

import (
	"fmt"
	"time"

	"github.com/pkg/errors"
	"github.com/roninzo/pointers"
	"github.com/roninzo/structs"
)

type structTest struct {
	String          string                 `json:"string,omitempty"`
	Bool            bool                   `json:"bool,omitempty"`
	Int             int                    `json:"int,omitempty"`
	Uint            uint                   `json:"uint,omitempty"`
	Float           float32                `json:"float,omitempty"`
	Complex         complex128             `json:"complex,omitempty"`
	Bytes           []byte                 `json:"bytes,omitempty"`
	Interface       interface{}            `json:"interface,omitempty"`
	Error           error                  `json:"error,omitempty"`
	Time            time.Time              `json:"time,omitempty"`
	Duration        time.Duration          `json:"duration,omitempty"`
	NestedStruct    structNested           `json:"nested_struct,omitempty"`
	PtrString       *string                `json:"pointer_string,omitempty"`
	PtrBool         *bool                  `json:"pointer_bool,omitempty"`
	PtrInt          *int                   `json:"pointer_int,omitempty"`
	PtrUint         *uint                  `json:"pointer_uint,omitempty"`
	PtrFloat        *float32               `json:"pointer_float,omitempty"`
	PtrComplex      *complex128            `json:"pointer_complex,omitempty"`
	PtrError        *error                 `json:"pointer_error,omitempty"`
	PtrTime         *time.Time             `json:"pointer_time,omitempty"`
	PtrDuration     *time.Duration         `json:"pointer_duration,omitempty"`
	PtrNestedStruct *structNested          `json:"pointer_nested_struct,omitempty"`
	MapString       map[string]string      `json:"map_string,omitempty"`
	MapBool         map[string]bool        `json:"map_bool,omitempty"`
	MapInt          map[string]int         `json:"mapint,omitempty"`
	MapUint         map[string]uint        `json:"map_uint,omitempty"`
	MapFloat        map[string]float32     `json:"map_float,omitempty"`
	MapComplex      map[string]complex128  `json:"map_complex,omitempty"`
	MapInterface    map[string]interface{} `json:"map_interface,omitempty"`
	SliceString     []string               `json:"slice_string,omitempty"`
	SliceBool       []bool                 `json:"slice_bool,omitempty"`
	SliceInt        []int                  `json:"slice_int,omitempty"`
	SliceUint       []uint                 `json:"slice_uint,omitempty"`
	SliceFloat      []float32              `json:"slice_float,omitempty"`
	SliceComplex    []complex128           `json:"slice_complex,omitempty"`
	SliceInterface  []interface{}          `json:"slice_interface,omitempty"`
	SlicePtrString  []*string              `json:"slice_pointer_string,omitempty"`
	SlicePtrBool    []*bool                `json:"slice_pointer_bool,omitempty"`
	SlicePtrInt     []*int                 `json:"slice_pointer_int,omitempty"`
	SlicePtrUint    []*uint                `json:"slice_pointer_uint,omitempty"`
	SlicePtrFloat   []*float32             `json:"slice_pointer_float,omitempty"`
	SlicePtrComplex []*complex128          `json:"slice_pointer_complex,omitempty"`
	Hidden          string                 `json:"-"`
	unexported      bool
}

type structNested struct {
	Uint   uint   `json:"uint,omitempty"`
	String string `json:"string,omitempty"`
}

var structFieldNames []string = []string{
	"String", "PtrString", "MapString", "SliceString", "SlicePtrString",
	"Bool", "PtrBool", "MapBool", "SliceBool", "SlicePtrBool",
	"Int", "PtrInt", "MapInt", "SliceInt", "SlicePtrInt",
	"Uint", "PtrUint", "MapUint", "SliceUint", "SlicePtrUint",
	"Float", "PtrFloat", "MapFloat", "SliceFloat", "SlicePtrFloat",
	"Complex", "PtrComplex", "MapComplex", "SliceComplex", "SlicePtrComplex",
	"Interface", "MapInterface", "SliceInterface",
	"Bytes",
	"Error", "PtrError",
	"Time", "PtrTime",
	"Duration", "PtrDuration",
	"NestedStruct", "PtrNestedStruct",
	"Hidden", "unexported",
}

var structX structTest = structTest{
	String:          "ozninoR",
	Bool:            false,
	Int:             3,
	Uint:            uint(654321),
	Float:           7622.50,
	Complex:         complex(-67, -42),
	Bytes:           []byte("Bye bye world"),
	Interface:       3.99,
	Error:           errors.New("not compliant"),
	Time:            time.Date(2021, time.August, 31, 14, 11, 11, 0, time.UTC),
	Duration:        30 * time.Second,
	NestedStruct:    structNested{Uint: 443211, String: "Microsoft IIS"},
	PtrString:       pointers.String("ozninoR"),
	PtrBool:         pointers.Bool(false),
	PtrInt:          pointers.Int(3),
	PtrUint:         pointers.Uint(uint(654321)),
	PtrFloat:        pointers.Float32(7622.50),
	PtrComplex:      pointers.Complex128(complex(-67, -42)),
	PtrError:        pointers.Error(errors.New("not compliant")),
	PtrTime:         pointers.Time(time.Date(2021, time.August, 31, 14, 11, 11, 0, time.UTC)),
	PtrDuration:     pointers.Duration(30 * time.Second),
	PtrNestedStruct: &structNested{Uint: 443211, String: "Microsoft IIS"},
	MapString:       map[string]string{"D": "four", "E": "five", "F": "six"},
	MapBool:         map[string]bool{"D": false, "E": true},
	MapInt:          map[string]int{"D": 4, "E": 5, "F": 6},
	MapUint:         map[string]uint{"D": uint(4), "E": uint(5), "F": uint(6)},
	MapFloat:        map[string]float32{"D": 1.4, "E": 1.5, "F": 1.6},
	MapComplex:      map[string]complex128{"D": complex(1, 4), "E": complex(1, 5), "F": complex(1, 6)},
	MapInterface:    map[string]interface{}{"D": 4, "E": "five", "F": 6.0},
	SliceString:     []string{"four", "five", "six"},
	SliceBool:       []bool{false, true},
	SliceInt:        []int{4, 5, 6},
	SliceUint:       []uint{uint(4), uint(5), uint(6)},
	SliceFloat:      []float32{1.4, 1.5, 1.6},
	SliceComplex:    []complex128{complex(1, 4), complex(1, 5), complex(1, 6)},
	SliceInterface:  []interface{}{4, "five", 6.0},
	SlicePtrString:  []*string{pointers.String("four"), pointers.String("five"), pointers.String("six")},
	SlicePtrBool:    []*bool{pointers.Bool(false), pointers.Bool(true)},
	SlicePtrInt:     []*int{pointers.Int(4), pointers.Int(5), pointers.Int(6)},
	SlicePtrUint:    []*uint{pointers.Uint(uint(4)), pointers.Uint(uint(5)), pointers.Uint(uint(6))},
	SlicePtrFloat:   []*float32{pointers.Float32(1.4), pointers.Float32(1.5), pointers.Float32(1.6)},
	SlicePtrComplex: []*complex128{pointers.Complex128(complex(1, 4)), pointers.Complex128(complex(1, 5)), pointers.Complex128(complex(1, 6))},
	Hidden:          "gfedcba",
	unexported:      false,
}

func printStruct(s *structTest) {

	format := "- %15s: %v.\n"
	formatStruct := "- %15s: %+v.\n"
	formatPointer := "- %15s: *%v.\n"
	formatPtrStruct := "- %15s: *%+v.\n"
	fmt.Printf(format, "String", s.String)
	fmt.Printf(format, "Bool", s.Bool)
	fmt.Printf(format, "Int", s.Int)
	fmt.Printf(format, "Uint", s.Uint)
	fmt.Printf(format, "Float", s.Float)
	fmt.Printf(format, "Complex", s.Complex)
	fmt.Printf(format, "Bytes", string(s.Bytes))
	fmt.Printf(format, "Interface", s.Interface)
	fmt.Printf(format, "Error", s.Error)
	fmt.Printf(format, "Time", s.Time)
	fmt.Printf(format, "Duration", s.Duration)
	fmt.Printf(formatStruct, "NestedStruct", s.NestedStruct)
	if s.PtrString != nil {
		fmt.Printf(formatPointer, "PtrString", *s.PtrString)
	} else {
		fmt.Printf(format, "PtrString", s.PtrString)
	}
	if s.PtrBool != nil {
		fmt.Printf(formatPointer, "PtrBool", *s.PtrBool)
	} else {
		fmt.Printf(format, "PtrBool", s.PtrBool)
	}
	if s.PtrInt != nil {
		fmt.Printf(formatPointer, "PtrInt", *s.PtrInt)
	} else {
		fmt.Printf(format, "PtrInt", s.PtrInt)
	}
	if s.PtrUint != nil {
		fmt.Printf(formatPointer, "PtrUint", *s.PtrUint)
	} else {
		fmt.Printf(format, "PtrUint", s.PtrUint)
	}
	if s.PtrFloat != nil {
		fmt.Printf(formatPointer, "PtrFloat", *s.PtrFloat)
	} else {
		fmt.Printf(format, "PtrFloat", s.PtrFloat)
	}
	if s.PtrComplex != nil {
		fmt.Printf(formatPointer, "PtrComplex", *s.PtrComplex)
	} else {
		fmt.Printf(format, "PtrComplex", s.PtrComplex)
	}
	if s.PtrError != nil {
		fmt.Printf(formatPointer, "PtrError", *s.PtrError)
	} else {
		fmt.Printf(format, "PtrError", s.PtrError)
	}
	if s.PtrTime != nil {
		fmt.Printf(formatPointer, "PtrTime", *s.PtrTime)
	} else {
		fmt.Printf(format, "PtrTime", s.PtrTime)
	}
	if s.PtrDuration != nil {
		fmt.Printf(formatPointer, "PtrDuration", *s.PtrDuration)
	} else {
		fmt.Printf(format, "PtrDuration", s.PtrDuration)
	}
	if s.PtrNestedStruct != nil {
		fmt.Printf(formatPtrStruct, "PtrNestedStruct", *s.PtrNestedStruct)
	} else {
		fmt.Printf(formatStruct, "PtrNestedStruct", s.PtrNestedStruct)
	}
	fmt.Printf(format, "MapString", s.MapString)
	fmt.Printf(format, "MapBool", s.MapBool)
	fmt.Printf(format, "MapInt", s.MapInt)
	fmt.Printf(format, "MapUint", s.MapUint)
	fmt.Printf(format, "MapFloat", s.MapFloat)
	fmt.Printf(format, "MapComplex", s.MapComplex)
	fmt.Printf(format, "MapInterface", s.MapInterface)
	fmt.Printf(format, "SliceString", s.SliceString)
	fmt.Printf(format, "SliceBool", s.SliceBool)
	fmt.Printf(format, "SliceInt", s.SliceInt)
	fmt.Printf(format, "SliceUint", s.SliceUint)
	fmt.Printf(format, "SliceFloat", s.SliceFloat)
	fmt.Printf(format, "SliceComplex", s.SliceComplex)
	fmt.Printf(format, "SliceInterface", s.SliceInterface)
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrString {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrString", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrBool {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrBool", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrInt {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrInt", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrUint {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrUint", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrFloat {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrFloat", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrComplex {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrComplex", m)
	}
	fmt.Printf(format, "Hidden", s.Hidden)
	fmt.Printf(format, "unexported", s.unexported)
}

func main() {
	t := structX

	s, err := structs.New(&t)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
		return
	}

	for _, name := range structFieldNames {
		err := s.Field(name).SetNil()
		if err != nil {
			fmt.Printf("SetNil[Error]: %v.\n", err)
		}
	}
	printStruct(&t)

}
Output:

SetNil[Error]: could not set field structTest.String to nil: struct field is not nillable.
SetNil[Error]: could not set field structTest.Bool to nil: struct field is not nillable.
SetNil[Error]: could not set field structTest.Int to nil: struct field is not nillable.
SetNil[Error]: could not set field structTest.Uint to nil: struct field is not nillable.
SetNil[Error]: could not set field structTest.Float to nil: struct field is not nillable.
SetNil[Error]: could not set field structTest.Complex to nil: struct field is not nillable.
SetNil[Error]: could not set field structTest.Time to nil: struct field is not nillable.
SetNil[Error]: could not set field structTest.Duration to nil: struct field is not nillable.
SetNil[Error]: could not set field structTest.NestedStruct to nil: struct field is not nillable.
SetNil[Error]: could not set field structTest.Hidden to nil: struct field is not nillable.
SetNil[Error]: could not set field structTest.unexported to nil: struct field is not settable.
-          String: ozninoR.
-            Bool: false.
-             Int: 3.
-            Uint: 654321.
-           Float: 7622.5.
-         Complex: (-67-42i).
-           Bytes: .
-       Interface: <nil>.
-           Error: <nil>.
-            Time: 2021-08-31 14:11:11 +0000 UTC.
-        Duration: 30s.
-    NestedStruct: {Uint:443211 String:Microsoft IIS}.
-       PtrString: <nil>.
-         PtrBool: <nil>.
-          PtrInt: <nil>.
-         PtrUint: <nil>.
-        PtrFloat: <nil>.
-      PtrComplex: <nil>.
-        PtrError: <nil>.
-         PtrTime: <nil>.
-     PtrDuration: <nil>.
- PtrNestedStruct: <nil>.
-       MapString: map[].
-         MapBool: map[].
-          MapInt: map[].
-         MapUint: map[].
-        MapFloat: map[].
-      MapComplex: map[].
-    MapInterface: map[].
-     SliceString: [].
-       SliceBool: [].
-        SliceInt: [].
-       SliceUint: [].
-      SliceFloat: [].
-    SliceComplex: [].
-  SliceInterface: [].
-  SlicePtrString: [].
-    SlicePtrBool: [].
-     SlicePtrInt: [].
-    SlicePtrUint: [].
-   SlicePtrFloat: [].
- SlicePtrComplex: [].
-          Hidden: gfedcba.
-      unexported: false.
Example (ValueToValue)
package main

import (
	"fmt"
	"time"

	"github.com/pkg/errors"
	"github.com/roninzo/pointers"
	"github.com/roninzo/structs"
)

type structTest struct {
	String          string                 `json:"string,omitempty"`
	Bool            bool                   `json:"bool,omitempty"`
	Int             int                    `json:"int,omitempty"`
	Uint            uint                   `json:"uint,omitempty"`
	Float           float32                `json:"float,omitempty"`
	Complex         complex128             `json:"complex,omitempty"`
	Bytes           []byte                 `json:"bytes,omitempty"`
	Interface       interface{}            `json:"interface,omitempty"`
	Error           error                  `json:"error,omitempty"`
	Time            time.Time              `json:"time,omitempty"`
	Duration        time.Duration          `json:"duration,omitempty"`
	NestedStruct    structNested           `json:"nested_struct,omitempty"`
	PtrString       *string                `json:"pointer_string,omitempty"`
	PtrBool         *bool                  `json:"pointer_bool,omitempty"`
	PtrInt          *int                   `json:"pointer_int,omitempty"`
	PtrUint         *uint                  `json:"pointer_uint,omitempty"`
	PtrFloat        *float32               `json:"pointer_float,omitempty"`
	PtrComplex      *complex128            `json:"pointer_complex,omitempty"`
	PtrError        *error                 `json:"pointer_error,omitempty"`
	PtrTime         *time.Time             `json:"pointer_time,omitempty"`
	PtrDuration     *time.Duration         `json:"pointer_duration,omitempty"`
	PtrNestedStruct *structNested          `json:"pointer_nested_struct,omitempty"`
	MapString       map[string]string      `json:"map_string,omitempty"`
	MapBool         map[string]bool        `json:"map_bool,omitempty"`
	MapInt          map[string]int         `json:"mapint,omitempty"`
	MapUint         map[string]uint        `json:"map_uint,omitempty"`
	MapFloat        map[string]float32     `json:"map_float,omitempty"`
	MapComplex      map[string]complex128  `json:"map_complex,omitempty"`
	MapInterface    map[string]interface{} `json:"map_interface,omitempty"`
	SliceString     []string               `json:"slice_string,omitempty"`
	SliceBool       []bool                 `json:"slice_bool,omitempty"`
	SliceInt        []int                  `json:"slice_int,omitempty"`
	SliceUint       []uint                 `json:"slice_uint,omitempty"`
	SliceFloat      []float32              `json:"slice_float,omitempty"`
	SliceComplex    []complex128           `json:"slice_complex,omitempty"`
	SliceInterface  []interface{}          `json:"slice_interface,omitempty"`
	SlicePtrString  []*string              `json:"slice_pointer_string,omitempty"`
	SlicePtrBool    []*bool                `json:"slice_pointer_bool,omitempty"`
	SlicePtrInt     []*int                 `json:"slice_pointer_int,omitempty"`
	SlicePtrUint    []*uint                `json:"slice_pointer_uint,omitempty"`
	SlicePtrFloat   []*float32             `json:"slice_pointer_float,omitempty"`
	SlicePtrComplex []*complex128          `json:"slice_pointer_complex,omitempty"`
	Hidden          string                 `json:"-"`
	unexported      bool
}

type structNested struct {
	Uint   uint   `json:"uint,omitempty"`
	String string `json:"string,omitempty"`
}

var structV structTest = structTest{
	String:          "Roninzo",
	Bool:            true,
	Int:             8,
	Uint:            uint(123456),
	Float:           1922.50,
	Complex:         complex(22, 50),
	Bytes:           []byte("Hello world"),
	Interface:       "anything",
	Error:           errors.New("rows not found"),
	Time:            time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
	Duration:        5 * time.Second,
	NestedStruct:    structNested{Uint: 122334, String: "Apache"},
	PtrString:       pointers.String("Roninzo"),
	PtrBool:         pointers.Bool(true),
	PtrInt:          pointers.Int(8),
	PtrUint:         pointers.Uint(uint(123456)),
	PtrFloat:        pointers.Float32(1922.50),
	PtrComplex:      pointers.Complex128(complex(22, 50)),
	PtrError:        pointers.Error(errors.New("rows not found")),
	PtrTime:         pointers.Time(time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC)),
	PtrDuration:     pointers.Duration(5 * time.Second),
	PtrNestedStruct: &structNested{Uint: 122334, String: "Apache"},
	MapString:       map[string]string{"A": "one", "B": "two", "C": "three"},
	MapBool:         map[string]bool{"A": true, "B": false},
	MapInt:          map[string]int{"A": 1, "B": 2, "C": 3},
	MapUint:         map[string]uint{"A": uint(1), "B": uint(2), "C": uint(3)},
	MapFloat:        map[string]float32{"A": 1.1, "B": 1.2, "C": 1.3},
	MapComplex:      map[string]complex128{"A": complex(1, 1), "B": complex(1, 2), "C": complex(1, 3)},
	MapInterface:    map[string]interface{}{"A": 1, "B": "two", "C": 3.0},
	SliceString:     []string{"one", "two", "three"},
	SliceBool:       []bool{true, false},
	SliceInt:        []int{1, 2, 3},
	SliceUint:       []uint{uint(1), uint(2), uint(3)},
	SliceFloat:      []float32{1.1, 1.2, 1.3},
	SliceComplex:    []complex128{complex(1, 1), complex(1, 2), complex(1, 3)},
	SliceInterface:  []interface{}{1, "two", 3.0},
	SlicePtrString:  []*string{pointers.String("one"), pointers.String("two"), pointers.String("three")},
	SlicePtrBool:    []*bool{pointers.Bool(true), pointers.Bool(false)},
	SlicePtrInt:     []*int{pointers.Int(1), pointers.Int(2), pointers.Int(3)},
	SlicePtrUint:    []*uint{pointers.Uint(uint(1)), pointers.Uint(uint(2)), pointers.Uint(uint(3))},
	SlicePtrFloat:   []*float32{pointers.Float32(1.1), pointers.Float32(1.2), pointers.Float32(1.3)},
	SlicePtrComplex: []*complex128{pointers.Complex128(complex(1, 1)), pointers.Complex128(complex(1, 2)), pointers.Complex128(complex(1, 3))},
	Hidden:          "abcdefg",
	unexported:      true,
}

var structX structTest = structTest{
	String:          "ozninoR",
	Bool:            false,
	Int:             3,
	Uint:            uint(654321),
	Float:           7622.50,
	Complex:         complex(-67, -42),
	Bytes:           []byte("Bye bye world"),
	Interface:       3.99,
	Error:           errors.New("not compliant"),
	Time:            time.Date(2021, time.August, 31, 14, 11, 11, 0, time.UTC),
	Duration:        30 * time.Second,
	NestedStruct:    structNested{Uint: 443211, String: "Microsoft IIS"},
	PtrString:       pointers.String("ozninoR"),
	PtrBool:         pointers.Bool(false),
	PtrInt:          pointers.Int(3),
	PtrUint:         pointers.Uint(uint(654321)),
	PtrFloat:        pointers.Float32(7622.50),
	PtrComplex:      pointers.Complex128(complex(-67, -42)),
	PtrError:        pointers.Error(errors.New("not compliant")),
	PtrTime:         pointers.Time(time.Date(2021, time.August, 31, 14, 11, 11, 0, time.UTC)),
	PtrDuration:     pointers.Duration(30 * time.Second),
	PtrNestedStruct: &structNested{Uint: 443211, String: "Microsoft IIS"},
	MapString:       map[string]string{"D": "four", "E": "five", "F": "six"},
	MapBool:         map[string]bool{"D": false, "E": true},
	MapInt:          map[string]int{"D": 4, "E": 5, "F": 6},
	MapUint:         map[string]uint{"D": uint(4), "E": uint(5), "F": uint(6)},
	MapFloat:        map[string]float32{"D": 1.4, "E": 1.5, "F": 1.6},
	MapComplex:      map[string]complex128{"D": complex(1, 4), "E": complex(1, 5), "F": complex(1, 6)},
	MapInterface:    map[string]interface{}{"D": 4, "E": "five", "F": 6.0},
	SliceString:     []string{"four", "five", "six"},
	SliceBool:       []bool{false, true},
	SliceInt:        []int{4, 5, 6},
	SliceUint:       []uint{uint(4), uint(5), uint(6)},
	SliceFloat:      []float32{1.4, 1.5, 1.6},
	SliceComplex:    []complex128{complex(1, 4), complex(1, 5), complex(1, 6)},
	SliceInterface:  []interface{}{4, "five", 6.0},
	SlicePtrString:  []*string{pointers.String("four"), pointers.String("five"), pointers.String("six")},
	SlicePtrBool:    []*bool{pointers.Bool(false), pointers.Bool(true)},
	SlicePtrInt:     []*int{pointers.Int(4), pointers.Int(5), pointers.Int(6)},
	SlicePtrUint:    []*uint{pointers.Uint(uint(4)), pointers.Uint(uint(5)), pointers.Uint(uint(6))},
	SlicePtrFloat:   []*float32{pointers.Float32(1.4), pointers.Float32(1.5), pointers.Float32(1.6)},
	SlicePtrComplex: []*complex128{pointers.Complex128(complex(1, 4)), pointers.Complex128(complex(1, 5)), pointers.Complex128(complex(1, 6))},
	Hidden:          "gfedcba",
	unexported:      false,
}

func printStruct(s *structTest) {

	format := "- %15s: %v.\n"
	formatStruct := "- %15s: %+v.\n"
	formatPointer := "- %15s: *%v.\n"
	formatPtrStruct := "- %15s: *%+v.\n"
	fmt.Printf(format, "String", s.String)
	fmt.Printf(format, "Bool", s.Bool)
	fmt.Printf(format, "Int", s.Int)
	fmt.Printf(format, "Uint", s.Uint)
	fmt.Printf(format, "Float", s.Float)
	fmt.Printf(format, "Complex", s.Complex)
	fmt.Printf(format, "Bytes", string(s.Bytes))
	fmt.Printf(format, "Interface", s.Interface)
	fmt.Printf(format, "Error", s.Error)
	fmt.Printf(format, "Time", s.Time)
	fmt.Printf(format, "Duration", s.Duration)
	fmt.Printf(formatStruct, "NestedStruct", s.NestedStruct)
	if s.PtrString != nil {
		fmt.Printf(formatPointer, "PtrString", *s.PtrString)
	} else {
		fmt.Printf(format, "PtrString", s.PtrString)
	}
	if s.PtrBool != nil {
		fmt.Printf(formatPointer, "PtrBool", *s.PtrBool)
	} else {
		fmt.Printf(format, "PtrBool", s.PtrBool)
	}
	if s.PtrInt != nil {
		fmt.Printf(formatPointer, "PtrInt", *s.PtrInt)
	} else {
		fmt.Printf(format, "PtrInt", s.PtrInt)
	}
	if s.PtrUint != nil {
		fmt.Printf(formatPointer, "PtrUint", *s.PtrUint)
	} else {
		fmt.Printf(format, "PtrUint", s.PtrUint)
	}
	if s.PtrFloat != nil {
		fmt.Printf(formatPointer, "PtrFloat", *s.PtrFloat)
	} else {
		fmt.Printf(format, "PtrFloat", s.PtrFloat)
	}
	if s.PtrComplex != nil {
		fmt.Printf(formatPointer, "PtrComplex", *s.PtrComplex)
	} else {
		fmt.Printf(format, "PtrComplex", s.PtrComplex)
	}
	if s.PtrError != nil {
		fmt.Printf(formatPointer, "PtrError", *s.PtrError)
	} else {
		fmt.Printf(format, "PtrError", s.PtrError)
	}
	if s.PtrTime != nil {
		fmt.Printf(formatPointer, "PtrTime", *s.PtrTime)
	} else {
		fmt.Printf(format, "PtrTime", s.PtrTime)
	}
	if s.PtrDuration != nil {
		fmt.Printf(formatPointer, "PtrDuration", *s.PtrDuration)
	} else {
		fmt.Printf(format, "PtrDuration", s.PtrDuration)
	}
	if s.PtrNestedStruct != nil {
		fmt.Printf(formatPtrStruct, "PtrNestedStruct", *s.PtrNestedStruct)
	} else {
		fmt.Printf(formatStruct, "PtrNestedStruct", s.PtrNestedStruct)
	}
	fmt.Printf(format, "MapString", s.MapString)
	fmt.Printf(format, "MapBool", s.MapBool)
	fmt.Printf(format, "MapInt", s.MapInt)
	fmt.Printf(format, "MapUint", s.MapUint)
	fmt.Printf(format, "MapFloat", s.MapFloat)
	fmt.Printf(format, "MapComplex", s.MapComplex)
	fmt.Printf(format, "MapInterface", s.MapInterface)
	fmt.Printf(format, "SliceString", s.SliceString)
	fmt.Printf(format, "SliceBool", s.SliceBool)
	fmt.Printf(format, "SliceInt", s.SliceInt)
	fmt.Printf(format, "SliceUint", s.SliceUint)
	fmt.Printf(format, "SliceFloat", s.SliceFloat)
	fmt.Printf(format, "SliceComplex", s.SliceComplex)
	fmt.Printf(format, "SliceInterface", s.SliceInterface)
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrString {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrString", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrBool {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrBool", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrInt {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrInt", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrUint {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrUint", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrFloat {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrFloat", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrComplex {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrComplex", m)
	}
	fmt.Printf(format, "Hidden", s.Hidden)
	fmt.Printf(format, "unexported", s.unexported)
}

func main() {
	t := structV

	s, err := structs.New(&t)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
		return
	}

	err = s.Field("String").Set(structX.String)
	err = s.Field("Bool").Set(structX.Bool)
	err = s.Field("Int").Set(structX.Int)
	err = s.Field("Uint").Set(structX.Uint)
	err = s.Field("Float").Set(structX.Float)
	err = s.Field("Complex").Set(structX.Complex)
	err = s.Field("Bytes").Set(structX.Bytes)
	err = s.Field("Interface").Set(structX.Interface)
	err = s.Field("Error").Set(structX.Error)
	err = s.Field("Time").Set(structX.Time)
	err = s.Field("Duration").Set(structX.Duration)
	err = s.Field("NestedStruct").Set(structX.NestedStruct)
	err = s.Field("PtrString").Set(structX.PtrString)
	err = s.Field("PtrBool").Set(structX.PtrBool)
	err = s.Field("PtrInt").Set(structX.PtrInt)
	err = s.Field("PtrUint").Set(structX.PtrUint)
	err = s.Field("PtrFloat").Set(structX.PtrFloat)
	err = s.Field("PtrComplex").Set(structX.PtrComplex)
	err = s.Field("PtrError").Set(structX.PtrError)
	err = s.Field("PtrTime").Set(structX.PtrTime)
	err = s.Field("PtrDuration").Set(structX.PtrDuration)
	err = s.Field("PtrNestedStruct").Set(structX.PtrNestedStruct)
	err = s.Field("MapString").Set(structX.MapString)
	err = s.Field("MapBool").Set(structX.MapBool)
	err = s.Field("MapInt").Set(structX.MapInt)
	err = s.Field("MapUint").Set(structX.MapUint)
	err = s.Field("MapFloat").Set(structX.MapFloat)
	err = s.Field("MapComplex").Set(structX.MapComplex)
	err = s.Field("MapInterface").Set(structX.MapInterface)
	err = s.Field("SliceString").Set(structX.SliceString)
	err = s.Field("SliceBool").Set(structX.SliceBool)
	err = s.Field("SliceInt").Set(structX.SliceInt)
	err = s.Field("SliceUint").Set(structX.SliceUint)
	err = s.Field("SliceFloat").Set(structX.SliceFloat)
	err = s.Field("SliceComplex").Set(structX.SliceComplex)
	err = s.Field("SliceInterface").Set(structX.SliceInterface)
	err = s.Field("SlicePtrString").Set(structX.SlicePtrString)
	err = s.Field("SlicePtrBool").Set(structX.SlicePtrBool)
	err = s.Field("SlicePtrInt").Set(structX.SlicePtrInt)
	err = s.Field("SlicePtrUint").Set(structX.SlicePtrUint)
	err = s.Field("SlicePtrFloat").Set(structX.SlicePtrFloat)
	err = s.Field("SlicePtrComplex").Set(structX.SlicePtrComplex)
	err = s.Field("Hidden").Set(structX.Hidden)
	err = s.Field("unexported").Set(structX.unexported)
	if err != nil {
		fmt.Printf("Set[Error]: %v.\n", err)
	}
	printStruct(&t)

}
Output:

Set[Error]: could not set field structTest.unexported: struct field is not settable.
-          String: ozninoR.
-            Bool: false.
-             Int: 3.
-            Uint: 654321.
-           Float: 7622.5.
-         Complex: (-67-42i).
-           Bytes: Bye bye world.
-       Interface: 3.99.
-           Error: not compliant.
-            Time: 2021-08-31 14:11:11 +0000 UTC.
-        Duration: 30s.
-    NestedStruct: {Uint:443211 String:Microsoft IIS}.
-       PtrString: *ozninoR.
-         PtrBool: *false.
-          PtrInt: *3.
-         PtrUint: *654321.
-        PtrFloat: *7622.5.
-      PtrComplex: *(-67-42i).
-        PtrError: *not compliant.
-         PtrTime: *2021-08-31 14:11:11 +0000 UTC.
-     PtrDuration: *30s.
- PtrNestedStruct: *{Uint:443211 String:Microsoft IIS}.
-       MapString: map[D:four E:five F:six].
-         MapBool: map[D:false E:true].
-          MapInt: map[D:4 E:5 F:6].
-         MapUint: map[D:4 E:5 F:6].
-        MapFloat: map[D:1.4 E:1.5 F:1.6].
-      MapComplex: map[D:(1+4i) E:(1+5i) F:(1+6i)].
-    MapInterface: map[D:4 E:five F:6].
-     SliceString: [four five six].
-       SliceBool: [false true].
-        SliceInt: [4 5 6].
-       SliceUint: [4 5 6].
-      SliceFloat: [1.4 1.5 1.6].
-    SliceComplex: [(1+4i) (1+5i) (1+6i)].
-  SliceInterface: [4 five 6].
-  SlicePtrString: [*four *five *six].
-    SlicePtrBool: [*false *true].
-     SlicePtrInt: [*4 *5 *6].
-    SlicePtrUint: [*4 *5 *6].
-   SlicePtrFloat: [*1.4 *1.5 *1.6].
- SlicePtrComplex: [*(1+4i) *(1+5i) *(1+6i)].
-          Hidden: gfedcba.
-      unexported: true.
Example (ValueToZero)
package main

import (
	"fmt"
	"time"

	"github.com/pkg/errors"
	"github.com/roninzo/pointers"
	"github.com/roninzo/structs"
)

type structTest struct {
	String          string                 `json:"string,omitempty"`
	Bool            bool                   `json:"bool,omitempty"`
	Int             int                    `json:"int,omitempty"`
	Uint            uint                   `json:"uint,omitempty"`
	Float           float32                `json:"float,omitempty"`
	Complex         complex128             `json:"complex,omitempty"`
	Bytes           []byte                 `json:"bytes,omitempty"`
	Interface       interface{}            `json:"interface,omitempty"`
	Error           error                  `json:"error,omitempty"`
	Time            time.Time              `json:"time,omitempty"`
	Duration        time.Duration          `json:"duration,omitempty"`
	NestedStruct    structNested           `json:"nested_struct,omitempty"`
	PtrString       *string                `json:"pointer_string,omitempty"`
	PtrBool         *bool                  `json:"pointer_bool,omitempty"`
	PtrInt          *int                   `json:"pointer_int,omitempty"`
	PtrUint         *uint                  `json:"pointer_uint,omitempty"`
	PtrFloat        *float32               `json:"pointer_float,omitempty"`
	PtrComplex      *complex128            `json:"pointer_complex,omitempty"`
	PtrError        *error                 `json:"pointer_error,omitempty"`
	PtrTime         *time.Time             `json:"pointer_time,omitempty"`
	PtrDuration     *time.Duration         `json:"pointer_duration,omitempty"`
	PtrNestedStruct *structNested          `json:"pointer_nested_struct,omitempty"`
	MapString       map[string]string      `json:"map_string,omitempty"`
	MapBool         map[string]bool        `json:"map_bool,omitempty"`
	MapInt          map[string]int         `json:"mapint,omitempty"`
	MapUint         map[string]uint        `json:"map_uint,omitempty"`
	MapFloat        map[string]float32     `json:"map_float,omitempty"`
	MapComplex      map[string]complex128  `json:"map_complex,omitempty"`
	MapInterface    map[string]interface{} `json:"map_interface,omitempty"`
	SliceString     []string               `json:"slice_string,omitempty"`
	SliceBool       []bool                 `json:"slice_bool,omitempty"`
	SliceInt        []int                  `json:"slice_int,omitempty"`
	SliceUint       []uint                 `json:"slice_uint,omitempty"`
	SliceFloat      []float32              `json:"slice_float,omitempty"`
	SliceComplex    []complex128           `json:"slice_complex,omitempty"`
	SliceInterface  []interface{}          `json:"slice_interface,omitempty"`
	SlicePtrString  []*string              `json:"slice_pointer_string,omitempty"`
	SlicePtrBool    []*bool                `json:"slice_pointer_bool,omitempty"`
	SlicePtrInt     []*int                 `json:"slice_pointer_int,omitempty"`
	SlicePtrUint    []*uint                `json:"slice_pointer_uint,omitempty"`
	SlicePtrFloat   []*float32             `json:"slice_pointer_float,omitempty"`
	SlicePtrComplex []*complex128          `json:"slice_pointer_complex,omitempty"`
	Hidden          string                 `json:"-"`
	unexported      bool
}

type structNested struct {
	Uint   uint   `json:"uint,omitempty"`
	String string `json:"string,omitempty"`
}

var structFieldNames []string = []string{
	"String", "PtrString", "MapString", "SliceString", "SlicePtrString",
	"Bool", "PtrBool", "MapBool", "SliceBool", "SlicePtrBool",
	"Int", "PtrInt", "MapInt", "SliceInt", "SlicePtrInt",
	"Uint", "PtrUint", "MapUint", "SliceUint", "SlicePtrUint",
	"Float", "PtrFloat", "MapFloat", "SliceFloat", "SlicePtrFloat",
	"Complex", "PtrComplex", "MapComplex", "SliceComplex", "SlicePtrComplex",
	"Interface", "MapInterface", "SliceInterface",
	"Bytes",
	"Error", "PtrError",
	"Time", "PtrTime",
	"Duration", "PtrDuration",
	"NestedStruct", "PtrNestedStruct",
	"Hidden", "unexported",
}

var structX structTest = structTest{
	String:          "ozninoR",
	Bool:            false,
	Int:             3,
	Uint:            uint(654321),
	Float:           7622.50,
	Complex:         complex(-67, -42),
	Bytes:           []byte("Bye bye world"),
	Interface:       3.99,
	Error:           errors.New("not compliant"),
	Time:            time.Date(2021, time.August, 31, 14, 11, 11, 0, time.UTC),
	Duration:        30 * time.Second,
	NestedStruct:    structNested{Uint: 443211, String: "Microsoft IIS"},
	PtrString:       pointers.String("ozninoR"),
	PtrBool:         pointers.Bool(false),
	PtrInt:          pointers.Int(3),
	PtrUint:         pointers.Uint(uint(654321)),
	PtrFloat:        pointers.Float32(7622.50),
	PtrComplex:      pointers.Complex128(complex(-67, -42)),
	PtrError:        pointers.Error(errors.New("not compliant")),
	PtrTime:         pointers.Time(time.Date(2021, time.August, 31, 14, 11, 11, 0, time.UTC)),
	PtrDuration:     pointers.Duration(30 * time.Second),
	PtrNestedStruct: &structNested{Uint: 443211, String: "Microsoft IIS"},
	MapString:       map[string]string{"D": "four", "E": "five", "F": "six"},
	MapBool:         map[string]bool{"D": false, "E": true},
	MapInt:          map[string]int{"D": 4, "E": 5, "F": 6},
	MapUint:         map[string]uint{"D": uint(4), "E": uint(5), "F": uint(6)},
	MapFloat:        map[string]float32{"D": 1.4, "E": 1.5, "F": 1.6},
	MapComplex:      map[string]complex128{"D": complex(1, 4), "E": complex(1, 5), "F": complex(1, 6)},
	MapInterface:    map[string]interface{}{"D": 4, "E": "five", "F": 6.0},
	SliceString:     []string{"four", "five", "six"},
	SliceBool:       []bool{false, true},
	SliceInt:        []int{4, 5, 6},
	SliceUint:       []uint{uint(4), uint(5), uint(6)},
	SliceFloat:      []float32{1.4, 1.5, 1.6},
	SliceComplex:    []complex128{complex(1, 4), complex(1, 5), complex(1, 6)},
	SliceInterface:  []interface{}{4, "five", 6.0},
	SlicePtrString:  []*string{pointers.String("four"), pointers.String("five"), pointers.String("six")},
	SlicePtrBool:    []*bool{pointers.Bool(false), pointers.Bool(true)},
	SlicePtrInt:     []*int{pointers.Int(4), pointers.Int(5), pointers.Int(6)},
	SlicePtrUint:    []*uint{pointers.Uint(uint(4)), pointers.Uint(uint(5)), pointers.Uint(uint(6))},
	SlicePtrFloat:   []*float32{pointers.Float32(1.4), pointers.Float32(1.5), pointers.Float32(1.6)},
	SlicePtrComplex: []*complex128{pointers.Complex128(complex(1, 4)), pointers.Complex128(complex(1, 5)), pointers.Complex128(complex(1, 6))},
	Hidden:          "gfedcba",
	unexported:      false,
}

func printStruct(s *structTest) {

	format := "- %15s: %v.\n"
	formatStruct := "- %15s: %+v.\n"
	formatPointer := "- %15s: *%v.\n"
	formatPtrStruct := "- %15s: *%+v.\n"
	fmt.Printf(format, "String", s.String)
	fmt.Printf(format, "Bool", s.Bool)
	fmt.Printf(format, "Int", s.Int)
	fmt.Printf(format, "Uint", s.Uint)
	fmt.Printf(format, "Float", s.Float)
	fmt.Printf(format, "Complex", s.Complex)
	fmt.Printf(format, "Bytes", string(s.Bytes))
	fmt.Printf(format, "Interface", s.Interface)
	fmt.Printf(format, "Error", s.Error)
	fmt.Printf(format, "Time", s.Time)
	fmt.Printf(format, "Duration", s.Duration)
	fmt.Printf(formatStruct, "NestedStruct", s.NestedStruct)
	if s.PtrString != nil {
		fmt.Printf(formatPointer, "PtrString", *s.PtrString)
	} else {
		fmt.Printf(format, "PtrString", s.PtrString)
	}
	if s.PtrBool != nil {
		fmt.Printf(formatPointer, "PtrBool", *s.PtrBool)
	} else {
		fmt.Printf(format, "PtrBool", s.PtrBool)
	}
	if s.PtrInt != nil {
		fmt.Printf(formatPointer, "PtrInt", *s.PtrInt)
	} else {
		fmt.Printf(format, "PtrInt", s.PtrInt)
	}
	if s.PtrUint != nil {
		fmt.Printf(formatPointer, "PtrUint", *s.PtrUint)
	} else {
		fmt.Printf(format, "PtrUint", s.PtrUint)
	}
	if s.PtrFloat != nil {
		fmt.Printf(formatPointer, "PtrFloat", *s.PtrFloat)
	} else {
		fmt.Printf(format, "PtrFloat", s.PtrFloat)
	}
	if s.PtrComplex != nil {
		fmt.Printf(formatPointer, "PtrComplex", *s.PtrComplex)
	} else {
		fmt.Printf(format, "PtrComplex", s.PtrComplex)
	}
	if s.PtrError != nil {
		fmt.Printf(formatPointer, "PtrError", *s.PtrError)
	} else {
		fmt.Printf(format, "PtrError", s.PtrError)
	}
	if s.PtrTime != nil {
		fmt.Printf(formatPointer, "PtrTime", *s.PtrTime)
	} else {
		fmt.Printf(format, "PtrTime", s.PtrTime)
	}
	if s.PtrDuration != nil {
		fmt.Printf(formatPointer, "PtrDuration", *s.PtrDuration)
	} else {
		fmt.Printf(format, "PtrDuration", s.PtrDuration)
	}
	if s.PtrNestedStruct != nil {
		fmt.Printf(formatPtrStruct, "PtrNestedStruct", *s.PtrNestedStruct)
	} else {
		fmt.Printf(formatStruct, "PtrNestedStruct", s.PtrNestedStruct)
	}
	fmt.Printf(format, "MapString", s.MapString)
	fmt.Printf(format, "MapBool", s.MapBool)
	fmt.Printf(format, "MapInt", s.MapInt)
	fmt.Printf(format, "MapUint", s.MapUint)
	fmt.Printf(format, "MapFloat", s.MapFloat)
	fmt.Printf(format, "MapComplex", s.MapComplex)
	fmt.Printf(format, "MapInterface", s.MapInterface)
	fmt.Printf(format, "SliceString", s.SliceString)
	fmt.Printf(format, "SliceBool", s.SliceBool)
	fmt.Printf(format, "SliceInt", s.SliceInt)
	fmt.Printf(format, "SliceUint", s.SliceUint)
	fmt.Printf(format, "SliceFloat", s.SliceFloat)
	fmt.Printf(format, "SliceComplex", s.SliceComplex)
	fmt.Printf(format, "SliceInterface", s.SliceInterface)
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrString {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrString", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrBool {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrBool", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrInt {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrInt", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrUint {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrUint", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrFloat {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrFloat", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrComplex {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrComplex", m)
	}
	fmt.Printf(format, "Hidden", s.Hidden)
	fmt.Printf(format, "unexported", s.unexported)
}

func main() {
	t := structX

	s, err := structs.New(&t)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
		return
	}

	for _, name := range structFieldNames {
		err := s.Field(name).SetZero()
		if err != nil {
			fmt.Printf("SetZero[Error]: %v.\n", err)
		}
	}
	printStruct(&t)

}
Output:

SetZero[Error]: could not set field structTest.unexported to zero-value: struct field is not settable.
-          String: .
-            Bool: false.
-             Int: 0.
-            Uint: 0.
-           Float: 0.
-         Complex: (0+0i).
-           Bytes: .
-       Interface: <nil>.
-           Error: <nil>.
-            Time: 0001-01-01 00:00:00 +0000 UTC.
-        Duration: 0s.
-    NestedStruct: {Uint:0 String:}.
-       PtrString: <nil>.
-         PtrBool: <nil>.
-          PtrInt: <nil>.
-         PtrUint: <nil>.
-        PtrFloat: <nil>.
-      PtrComplex: <nil>.
-        PtrError: <nil>.
-         PtrTime: <nil>.
-     PtrDuration: <nil>.
- PtrNestedStruct: <nil>.
-       MapString: map[].
-         MapBool: map[].
-          MapInt: map[].
-         MapUint: map[].
-        MapFloat: map[].
-      MapComplex: map[].
-    MapInterface: map[].
-     SliceString: [].
-       SliceBool: [].
-        SliceInt: [].
-       SliceUint: [].
-      SliceFloat: [].
-    SliceComplex: [].
-  SliceInterface: [].
-  SlicePtrString: [].
-    SlicePtrBool: [].
-     SlicePtrInt: [].
-    SlicePtrUint: [].
-   SlicePtrFloat: [].
- SlicePtrComplex: [].
-          Hidden: .
-      unexported: false.
Example (ZeroToValue)
package main

import (
	"fmt"
	"time"

	"github.com/pkg/errors"
	"github.com/roninzo/pointers"
	"github.com/roninzo/structs"
)

type structTest struct {
	String          string                 `json:"string,omitempty"`
	Bool            bool                   `json:"bool,omitempty"`
	Int             int                    `json:"int,omitempty"`
	Uint            uint                   `json:"uint,omitempty"`
	Float           float32                `json:"float,omitempty"`
	Complex         complex128             `json:"complex,omitempty"`
	Bytes           []byte                 `json:"bytes,omitempty"`
	Interface       interface{}            `json:"interface,omitempty"`
	Error           error                  `json:"error,omitempty"`
	Time            time.Time              `json:"time,omitempty"`
	Duration        time.Duration          `json:"duration,omitempty"`
	NestedStruct    structNested           `json:"nested_struct,omitempty"`
	PtrString       *string                `json:"pointer_string,omitempty"`
	PtrBool         *bool                  `json:"pointer_bool,omitempty"`
	PtrInt          *int                   `json:"pointer_int,omitempty"`
	PtrUint         *uint                  `json:"pointer_uint,omitempty"`
	PtrFloat        *float32               `json:"pointer_float,omitempty"`
	PtrComplex      *complex128            `json:"pointer_complex,omitempty"`
	PtrError        *error                 `json:"pointer_error,omitempty"`
	PtrTime         *time.Time             `json:"pointer_time,omitempty"`
	PtrDuration     *time.Duration         `json:"pointer_duration,omitempty"`
	PtrNestedStruct *structNested          `json:"pointer_nested_struct,omitempty"`
	MapString       map[string]string      `json:"map_string,omitempty"`
	MapBool         map[string]bool        `json:"map_bool,omitempty"`
	MapInt          map[string]int         `json:"mapint,omitempty"`
	MapUint         map[string]uint        `json:"map_uint,omitempty"`
	MapFloat        map[string]float32     `json:"map_float,omitempty"`
	MapComplex      map[string]complex128  `json:"map_complex,omitempty"`
	MapInterface    map[string]interface{} `json:"map_interface,omitempty"`
	SliceString     []string               `json:"slice_string,omitempty"`
	SliceBool       []bool                 `json:"slice_bool,omitempty"`
	SliceInt        []int                  `json:"slice_int,omitempty"`
	SliceUint       []uint                 `json:"slice_uint,omitempty"`
	SliceFloat      []float32              `json:"slice_float,omitempty"`
	SliceComplex    []complex128           `json:"slice_complex,omitempty"`
	SliceInterface  []interface{}          `json:"slice_interface,omitempty"`
	SlicePtrString  []*string              `json:"slice_pointer_string,omitempty"`
	SlicePtrBool    []*bool                `json:"slice_pointer_bool,omitempty"`
	SlicePtrInt     []*int                 `json:"slice_pointer_int,omitempty"`
	SlicePtrUint    []*uint                `json:"slice_pointer_uint,omitempty"`
	SlicePtrFloat   []*float32             `json:"slice_pointer_float,omitempty"`
	SlicePtrComplex []*complex128          `json:"slice_pointer_complex,omitempty"`
	Hidden          string                 `json:"-"`
	unexported      bool
}

type structNested struct {
	Uint   uint   `json:"uint,omitempty"`
	String string `json:"string,omitempty"`
}

var structV structTest = structTest{
	String:          "Roninzo",
	Bool:            true,
	Int:             8,
	Uint:            uint(123456),
	Float:           1922.50,
	Complex:         complex(22, 50),
	Bytes:           []byte("Hello world"),
	Interface:       "anything",
	Error:           errors.New("rows not found"),
	Time:            time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
	Duration:        5 * time.Second,
	NestedStruct:    structNested{Uint: 122334, String: "Apache"},
	PtrString:       pointers.String("Roninzo"),
	PtrBool:         pointers.Bool(true),
	PtrInt:          pointers.Int(8),
	PtrUint:         pointers.Uint(uint(123456)),
	PtrFloat:        pointers.Float32(1922.50),
	PtrComplex:      pointers.Complex128(complex(22, 50)),
	PtrError:        pointers.Error(errors.New("rows not found")),
	PtrTime:         pointers.Time(time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC)),
	PtrDuration:     pointers.Duration(5 * time.Second),
	PtrNestedStruct: &structNested{Uint: 122334, String: "Apache"},
	MapString:       map[string]string{"A": "one", "B": "two", "C": "three"},
	MapBool:         map[string]bool{"A": true, "B": false},
	MapInt:          map[string]int{"A": 1, "B": 2, "C": 3},
	MapUint:         map[string]uint{"A": uint(1), "B": uint(2), "C": uint(3)},
	MapFloat:        map[string]float32{"A": 1.1, "B": 1.2, "C": 1.3},
	MapComplex:      map[string]complex128{"A": complex(1, 1), "B": complex(1, 2), "C": complex(1, 3)},
	MapInterface:    map[string]interface{}{"A": 1, "B": "two", "C": 3.0},
	SliceString:     []string{"one", "two", "three"},
	SliceBool:       []bool{true, false},
	SliceInt:        []int{1, 2, 3},
	SliceUint:       []uint{uint(1), uint(2), uint(3)},
	SliceFloat:      []float32{1.1, 1.2, 1.3},
	SliceComplex:    []complex128{complex(1, 1), complex(1, 2), complex(1, 3)},
	SliceInterface:  []interface{}{1, "two", 3.0},
	SlicePtrString:  []*string{pointers.String("one"), pointers.String("two"), pointers.String("three")},
	SlicePtrBool:    []*bool{pointers.Bool(true), pointers.Bool(false)},
	SlicePtrInt:     []*int{pointers.Int(1), pointers.Int(2), pointers.Int(3)},
	SlicePtrUint:    []*uint{pointers.Uint(uint(1)), pointers.Uint(uint(2)), pointers.Uint(uint(3))},
	SlicePtrFloat:   []*float32{pointers.Float32(1.1), pointers.Float32(1.2), pointers.Float32(1.3)},
	SlicePtrComplex: []*complex128{pointers.Complex128(complex(1, 1)), pointers.Complex128(complex(1, 2)), pointers.Complex128(complex(1, 3))},
	Hidden:          "abcdefg",
	unexported:      true,
}

func printStruct(s *structTest) {

	format := "- %15s: %v.\n"
	formatStruct := "- %15s: %+v.\n"
	formatPointer := "- %15s: *%v.\n"
	formatPtrStruct := "- %15s: *%+v.\n"
	fmt.Printf(format, "String", s.String)
	fmt.Printf(format, "Bool", s.Bool)
	fmt.Printf(format, "Int", s.Int)
	fmt.Printf(format, "Uint", s.Uint)
	fmt.Printf(format, "Float", s.Float)
	fmt.Printf(format, "Complex", s.Complex)
	fmt.Printf(format, "Bytes", string(s.Bytes))
	fmt.Printf(format, "Interface", s.Interface)
	fmt.Printf(format, "Error", s.Error)
	fmt.Printf(format, "Time", s.Time)
	fmt.Printf(format, "Duration", s.Duration)
	fmt.Printf(formatStruct, "NestedStruct", s.NestedStruct)
	if s.PtrString != nil {
		fmt.Printf(formatPointer, "PtrString", *s.PtrString)
	} else {
		fmt.Printf(format, "PtrString", s.PtrString)
	}
	if s.PtrBool != nil {
		fmt.Printf(formatPointer, "PtrBool", *s.PtrBool)
	} else {
		fmt.Printf(format, "PtrBool", s.PtrBool)
	}
	if s.PtrInt != nil {
		fmt.Printf(formatPointer, "PtrInt", *s.PtrInt)
	} else {
		fmt.Printf(format, "PtrInt", s.PtrInt)
	}
	if s.PtrUint != nil {
		fmt.Printf(formatPointer, "PtrUint", *s.PtrUint)
	} else {
		fmt.Printf(format, "PtrUint", s.PtrUint)
	}
	if s.PtrFloat != nil {
		fmt.Printf(formatPointer, "PtrFloat", *s.PtrFloat)
	} else {
		fmt.Printf(format, "PtrFloat", s.PtrFloat)
	}
	if s.PtrComplex != nil {
		fmt.Printf(formatPointer, "PtrComplex", *s.PtrComplex)
	} else {
		fmt.Printf(format, "PtrComplex", s.PtrComplex)
	}
	if s.PtrError != nil {
		fmt.Printf(formatPointer, "PtrError", *s.PtrError)
	} else {
		fmt.Printf(format, "PtrError", s.PtrError)
	}
	if s.PtrTime != nil {
		fmt.Printf(formatPointer, "PtrTime", *s.PtrTime)
	} else {
		fmt.Printf(format, "PtrTime", s.PtrTime)
	}
	if s.PtrDuration != nil {
		fmt.Printf(formatPointer, "PtrDuration", *s.PtrDuration)
	} else {
		fmt.Printf(format, "PtrDuration", s.PtrDuration)
	}
	if s.PtrNestedStruct != nil {
		fmt.Printf(formatPtrStruct, "PtrNestedStruct", *s.PtrNestedStruct)
	} else {
		fmt.Printf(formatStruct, "PtrNestedStruct", s.PtrNestedStruct)
	}
	fmt.Printf(format, "MapString", s.MapString)
	fmt.Printf(format, "MapBool", s.MapBool)
	fmt.Printf(format, "MapInt", s.MapInt)
	fmt.Printf(format, "MapUint", s.MapUint)
	fmt.Printf(format, "MapFloat", s.MapFloat)
	fmt.Printf(format, "MapComplex", s.MapComplex)
	fmt.Printf(format, "MapInterface", s.MapInterface)
	fmt.Printf(format, "SliceString", s.SliceString)
	fmt.Printf(format, "SliceBool", s.SliceBool)
	fmt.Printf(format, "SliceInt", s.SliceInt)
	fmt.Printf(format, "SliceUint", s.SliceUint)
	fmt.Printf(format, "SliceFloat", s.SliceFloat)
	fmt.Printf(format, "SliceComplex", s.SliceComplex)
	fmt.Printf(format, "SliceInterface", s.SliceInterface)
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrString {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrString", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrBool {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrBool", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrInt {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrInt", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrUint {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrUint", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrFloat {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrFloat", m)
	}
	{
		m := make([]interface{}, 0)
		for _, ptr := range s.SlicePtrComplex {
			if ptr != nil {
				v := fmt.Sprintf("*%v", *ptr)
				m = append(m, v)
				continue
			}
			m = append(m, nil)
		}
		fmt.Printf(format, "SlicePtrComplex", m)
	}
	fmt.Printf(format, "Hidden", s.Hidden)
	fmt.Printf(format, "unexported", s.unexported)
}

func main() {
	t := structTest{}

	s, err := structs.New(&t)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
		return
	}

	err = s.Field("String").Set(structV.String)
	err = s.Field("Bool").Set(structV.Bool)
	err = s.Field("Int").Set(structV.Int)
	err = s.Field("Uint").Set(structV.Uint)
	err = s.Field("Float").Set(structV.Float)
	err = s.Field("Complex").Set(structV.Complex)
	err = s.Field("Bytes").Set(structV.Bytes)
	err = s.Field("Interface").Set(structV.Interface)
	err = s.Field("Error").Set(structV.Error)
	err = s.Field("Time").Set(structV.Time)
	err = s.Field("Duration").Set(structV.Duration)
	err = s.Field("NestedStruct").Set(structV.NestedStruct)
	err = s.Field("PtrString").Set(structV.PtrString)
	err = s.Field("PtrBool").Set(structV.PtrBool)
	err = s.Field("PtrInt").Set(structV.PtrInt)
	err = s.Field("PtrUint").Set(structV.PtrUint)
	err = s.Field("PtrFloat").Set(structV.PtrFloat)
	err = s.Field("PtrComplex").Set(structV.PtrComplex)
	err = s.Field("PtrError").Set(structV.PtrError)
	err = s.Field("PtrTime").Set(structV.PtrTime)
	err = s.Field("PtrDuration").Set(structV.PtrDuration)
	err = s.Field("PtrNestedStruct").Set(structV.PtrNestedStruct)
	err = s.Field("MapString").Set(structV.MapString)
	err = s.Field("MapBool").Set(structV.MapBool)
	err = s.Field("MapInt").Set(structV.MapInt)
	err = s.Field("MapUint").Set(structV.MapUint)
	err = s.Field("MapFloat").Set(structV.MapFloat)
	err = s.Field("MapComplex").Set(structV.MapComplex)
	err = s.Field("MapInterface").Set(structV.MapInterface)
	err = s.Field("SliceString").Set(structV.SliceString)
	err = s.Field("SliceBool").Set(structV.SliceBool)
	err = s.Field("SliceInt").Set(structV.SliceInt)
	err = s.Field("SliceUint").Set(structV.SliceUint)
	err = s.Field("SliceFloat").Set(structV.SliceFloat)
	err = s.Field("SliceComplex").Set(structV.SliceComplex)
	err = s.Field("SliceInterface").Set(structV.SliceInterface)
	err = s.Field("SlicePtrString").Set(structV.SlicePtrString)
	err = s.Field("SlicePtrBool").Set(structV.SlicePtrBool)
	err = s.Field("SlicePtrInt").Set(structV.SlicePtrInt)
	err = s.Field("SlicePtrUint").Set(structV.SlicePtrUint)
	err = s.Field("SlicePtrFloat").Set(structV.SlicePtrFloat)
	err = s.Field("SlicePtrComplex").Set(structV.SlicePtrComplex)
	err = s.Field("Hidden").Set(structV.Hidden)
	err = s.Field("unexported").Set(structV.unexported)
	if err != nil {
		fmt.Printf("Set[Error]: %v.\n", err)
	}
	printStruct(&t)

}
Output:

Set[Error]: could not set field structTest.unexported: struct field is not settable.
-          String: Roninzo.
-            Bool: true.
-             Int: 8.
-            Uint: 123456.
-           Float: 1922.5.
-         Complex: (22+50i).
-           Bytes: Hello world.
-       Interface: anything.
-           Error: rows not found.
-            Time: 2021-08-03 16:44:46 +0000 UTC.
-        Duration: 5s.
-    NestedStruct: {Uint:122334 String:Apache}.
-       PtrString: *Roninzo.
-         PtrBool: *true.
-          PtrInt: *8.
-         PtrUint: *123456.
-        PtrFloat: *1922.5.
-      PtrComplex: *(22+50i).
-        PtrError: *rows not found.
-         PtrTime: *2021-08-03 16:44:46 +0000 UTC.
-     PtrDuration: *5s.
- PtrNestedStruct: *{Uint:122334 String:Apache}.
-       MapString: map[A:one B:two C:three].
-         MapBool: map[A:true B:false].
-          MapInt: map[A:1 B:2 C:3].
-         MapUint: map[A:1 B:2 C:3].
-        MapFloat: map[A:1.1 B:1.2 C:1.3].
-      MapComplex: map[A:(1+1i) B:(1+2i) C:(1+3i)].
-    MapInterface: map[A:1 B:two C:3].
-     SliceString: [one two three].
-       SliceBool: [true false].
-        SliceInt: [1 2 3].
-       SliceUint: [1 2 3].
-      SliceFloat: [1.1 1.2 1.3].
-    SliceComplex: [(1+1i) (1+2i) (1+3i)].
-  SliceInterface: [1 two 3].
-  SlicePtrString: [*one *two *three].
-    SlicePtrBool: [*true *false].
-     SlicePtrInt: [*1 *2 *3].
-    SlicePtrUint: [*1 *2 *3].
-   SlicePtrFloat: [*1.1 *1.2 *1.3].
- SlicePtrComplex: [*(1+1i) *(1+2i) *(1+3i)].
-          Hidden: abcdefg.
-      unexported: false.

func (*StructField) SetBool

func (f *StructField) SetBool(x bool)

SetBool sets the field to the bool value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Enabled bool `json:"enabled,omitempty"`
	}

	server := Server{
		Enabled: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("Enabled")

	if f.CanBool() {
		fmt.Printf("Bool: %v.\n", f.Bool())
		f.SetBool(false)
		fmt.Printf("SetBool: %v.\n", f.Bool())
	}

}
Output:

Bool: true.
SetBool: false.

func (*StructField) SetBytes

func (f *StructField) SetBytes(x []byte)

SetBytes sets the field to the slice of bytes value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Stream []byte `json:"stream,omitempty"`
	}

	server := Server{
		Stream: []byte("Hello world"),
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("Stream")

	if f.CanBytes() {
		b := f.Bytes()
		fmt.Printf("Bytes: %v.\n", b)
		fmt.Printf("BytesString: %v.\n", string(b))
		f.SetBytes([]byte("Bye bye world"))
		b = f.Bytes()
		fmt.Printf("SetBytes: %v.\n", b)
		fmt.Printf("SetBytesString: %v.\n", string(b))
	}

}
Output:

Bytes: [72 101 108 108 111 32 119 111 114 108 100].
BytesString: Hello world.
SetBytes: [66 121 101 32 98 121 101 32 119 111 114 108 100].
SetBytesString: Bye bye world.

func (*StructField) SetComplex

func (f *StructField) SetComplex(x complex128)

SetComplex sets the field to the complex128 value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Complex complex128 `json:"complex,omitempty"`
	}

	server := Server{
		Complex: complex(22, 50),
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("Complex")

	if f.CanComplex() {
		fmt.Printf("Complex: %v.\n", f.Complex())
		f.SetComplex(complex(77, 2))
		fmt.Printf("SetComplex: %v.\n", f.Complex())
	}

}
Output:

Complex: (22+50i).
SetComplex: (77+2i).

func (*StructField) SetDuration

func (f *StructField) SetDuration(x time.Duration)

SetDuration sets the field to the time.Duration value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		TimeOut time.Duration `json:"time_out,omitempty"`
	}

	server := Server{
		TimeOut: 5 * time.Second,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("TimeOut")

	if f.CanDuration() {
		fmt.Printf("Duration: %v.\n", f.Duration())
		f.SetDuration(30 * time.Second)
		fmt.Printf("SetDuration: %v.\n", f.Duration())
	}

}
Output:

Duration: 5s.
SetDuration: 30s.

func (*StructField) SetError

func (f *StructField) SetError(x error)

SetError sets the field to the error value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/pkg/errors"
	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Err error `json:"err,omitempty"`
	}

	server := Server{
		Err: errors.New("rows not found"),
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("Err")

	if f.CanError() {
		fmt.Printf("Error: %v.\n", f.Error())
		err := errors.Wrap(f.Error(), "empty table")
		f.SetError(err)
		fmt.Printf("SetError: %v.\n", f.Error())
	}

}
Output:

Error: rows not found.
SetError: empty table: rows not found.

func (*StructField) SetFloat

func (f *StructField) SetFloat(x float64)

SetFloat sets the field to the float64 value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Price float32 `json:"price,omitempty"`
	}

	server := Server{
		Price: 22.50,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("Price")

	if f.CanFloat() {
		fmt.Printf("Float: %v.\n", f.Float())
		f.SetFloat(450.50)
		fmt.Printf("SetUint: %v.\n", f.Float())
	}

}
Output:

Float: 22.5.
SetUint: 450.5.

func (*StructField) SetInt

func (f *StructField) SetInt(x int64)

SetInt sets the field to the int64 value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int `json:"count,omitempty"`
	}

	server := Server{
		Count: 123456,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("Count")

	if f.CanInt() {
		fmt.Printf("Int: %v.\n", f.Int())
		f.SetInt(654321)
		fmt.Printf("SetInt: %v.\n", f.Int())
	}

}
Output:

Int: 123456.
SetInt: 654321.

func (*StructField) SetInterface

func (f *StructField) SetInterface(x interface{})

SetInterface sets the field to the interface value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Anything interface{} `json:"anything,omitempty"`
	}

	server := Server{
		Anything: 654321,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("Anything")

	if f.CanInterface() {
		fmt.Printf("Interface: %v.\n", f.Interface())
		f.SetInterface(123456)
		fmt.Printf("SetInterface: %v.\n", f.Interface())
	}

}
Output:

Interface: 654321.
SetInterface: 123456.

func (*StructField) SetNil

func (f *StructField) SetNil() error

SetNil sets the field to its zero value. Unsettable/Un-nillable struct fields will return an error.

func (*StructField) SetString

func (f *StructField) SetString(x string)

SetString sets the field to the string value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name string `json:"name,omitempty"`
	}

	server := Server{
		Name: "Roninzo",
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("Name")

	if f.CanString() {
		fmt.Printf("String: %v.\n", f.String())
		f.SetString("ozninoR")
		fmt.Printf("SetString: %v.\n", f.String())
	}

}
Output:

String: Roninzo.
SetString: ozninoR.

func (*StructField) SetStruct

func (f *StructField) SetStruct(x *StructValue)

SetStruct sets the field to the StructValue value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Program *Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Program: &program,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("Program")

	if f.CanStruct() {
		fmt.Printf("Struct: %v.\n", server.Program.Name)
		program2 := Program{
			Name: "Microsoft IIS",
		}
		p, err := structs.New(&program2)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
		}
		f.SetStruct(p)
		fmt.Printf("SetStruct: %v.\n", server.Program.Name)
	}

}
Output:

Struct: Apache.
SetStruct: Microsoft IIS.

func (*StructField) SetTime

func (f *StructField) SetTime(x time.Time)

SetTime sets the field to the time.Time value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		ChangedAt time.Time `json:"changed_at,omitempty"`
	}

	server := Server{
		ChangedAt: time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("ChangedAt")

	if f.CanTime() {
		fmt.Printf("Time: %v.\n", f.Time())
		t := time.Date(2021, time.August, 31, 12, 30, 11, 0, time.UTC)
		f.SetTime(t)
		fmt.Printf("SetTime: %v.\n", f.Time())
	}

}
Output:

Time: 2021-08-03 16:44:46 +0000 UTC.
SetTime: 2021-08-31 12:30:11 +0000 UTC.

func (*StructField) SetUint

func (f *StructField) SetUint(x uint64)

SetUint sets the field to the uint64 value x. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		ID uint `json:"id,omitempty"`
	}

	server := Server{
		ID: 123456,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f := s.Field("ID")

	if f.CanUint() {
		fmt.Printf("Uint: %v.\n", f.Uint())
		f.SetUint(654321)
		fmt.Printf("SetUint: %v.\n", f.Uint())
	}

}
Output:

Uint: 123456.
SetUint: 654321.

func (*StructField) SetZero

func (f *StructField) SetZero() error

SetZero sets the field to its zero value. Unsettable struct fields will return an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Count")
	f3 := s.Field("unexported")

	fmt.Printf("Value: %v.\n", f1.Value())
	fmt.Printf("Value: %v.\n", f2.Value())
	fmt.Printf("Value: %v.\n", f3.Value())

	err1 := f1.SetZero()
	err2 := f2.SetZero()
	err3 := f3.SetZero()

	fmt.Printf("SetZero: %v.\n", f1.Value())
	fmt.Printf("SetZero: %v.\n", f2.Value())
	fmt.Printf("SetZero: %v.\n", f3.Value())
	fmt.Printf("Error: %v.\n", err1)
	fmt.Printf("Error: %v.\n", err2)
	fmt.Printf("Error: %v.\n", err3)

}
Output:

Value: Roninzo.
Value: 0.
Value: false.
SetZero: .
SetZero: 0.
SetZero: false.
Error: <nil>.
Error: <nil>.
Error: could not set field Server.unexported to zero-value: struct field is not settable.

func (*StructField) String

func (f *StructField) String() string
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field("ID")
	f2 := s.Field("Name")

	if f1.CanString() {
		fmt.Printf("String: %v.\n", f1.String())
	}
	if f2.CanString() {
		fmt.Printf("String: %v.\n", f2.String())
	}

}
Output:

String: Roninzo.

func (*StructField) Struct

func (f *StructField) Struct() *StructValue

Struct returns nested struct from field or nil if f is not a nested struct.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name     string  `json:"name,omitempty"`
		ID       uint    `json:"id,omitempty"`
		Enabled  bool    `json:"enabled,omitempty"`
		Count    int32   `json:"count,omitempty"`
		Password string  `json:"-"`
		Program  Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  program,
	}

	s1, _ := structs.New(&server)
	s2 := s1.Field("Program").Struct()

	fmt.Printf("Struct: %v\n", s1.Name())
	fmt.Printf("Struct: %v\n", s2.Name())

}
Output:

Struct: Server
Struct: Program

func (*StructField) Tag

func (f *StructField) Tag(key string) (string, bool)

Tag returns the value associated with key in the tag string. If the key is present in the tag the value (which may be empty) is returned. Otherwise the returned value will be the empty string. The ok return value reports whether the value was explicitly set in the tag string.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	t1, _ := s.Field(0).Tag("json")
	t2, _ := s.Field("Enabled").Tag("json")

	fmt.Printf("Tag: %v\n", t1)
	fmt.Printf("Tag: %v\n", t2)

}
Output:

Tag: name,omitempty
Tag: enabled,omitempty

func (*StructField) Time

func (f *StructField) Time() time.Time
Example
package main

import (
	"fmt"
	"time"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string    `json:"name,omitempty"`
		ID         uint      `json:"id,omitempty"`
		Enabled    bool      `json:"enabled,omitempty"`
		ChangedAt  time.Time `json:"changed_at,omitempty"`
		Password   string    `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		ChangedAt:  time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("ChangedAt")

	if f1.CanTime() {
		fmt.Printf("Time: %v\n", f1.Time())
	}
	if f2.CanTime() {
		fmt.Printf("Time: %v\n", f2.Time())
	}

}
Output:

Time: 2021-08-03 16:44:46 +0000 UTC

func (*StructField) Type

func (f *StructField) Type() reflect.Type

Type returns the underlying type of the field.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Enabled")

	fmt.Printf("Type: %v\n", s.Type())
	fmt.Printf("Type: %v\n", f1.Type())
	fmt.Printf("Type: %v\n", f2.Type())

}
Output:

Type: structs_test.Server
Type: string
Type: bool

func (*StructField) Uint

func (f *StructField) Uint() uint64
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("ID")

	if f1.CanUint() {
		fmt.Printf("Uint: %v\n", f1.Uint())
	}
	if f2.CanUint() {
		fmt.Printf("Uint: %v\n", f2.Uint())
	}

}
Output:

Uint: 123456

func (*StructField) Value

func (f *StructField) Value() reflect.Value

Value returns the underlying value of the field. Unexported struct fields will be neglected.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Enabled")

	fmt.Printf("Value: %v\n", f1.Value())
	fmt.Printf("Value: %v\n", f2.Value())

}
Output:

Value: Roninzo
Value: true

func (*StructField) Zero

func (f *StructField) Zero() reflect.Value

Zero returns field's type specific zero value. For instance, the zero-value of a string field is "", of an int is 0, and so on.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      5,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field("Enabled")
	f2 := s.Field("Count")

	fmt.Printf("Zero: %v\n", f1.Zero())
	fmt.Printf("Zero: %v\n", f2.Zero())

}
Output:

Zero: false
Zero: 0

type StructFields

type StructFields []*StructField

StructFields represents all struct fields that encapsulates high level functions around the struct fields.

func Fields

func Fields(dest interface{}) (StructFields, error)

Fields returns a slice of *StructField. For more info refer to StructValue types Fields() method. It returns an error if s's kind is not struct.

func (StructFields) Names

func (fields StructFields) Names() []string

Names returns all the field names of the struct. This method is not recursive, which means that nested structs must be dealt with explicitly.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Module struct {
		Name string `json:"name"`
	}

	type Server struct {
		Name       *string `json:"name,omitempty"`
		ID         uint    `json:"id,omitempty"`
		Enabled    bool    `json:"enabled,omitempty"`
		Count      int32   `json:"count,omitempty"`
		Password   string  `json:"-"`
		unexported bool
		Module     *Module `json:"module"`
	}

	var name string = "Roninzo"
	server := Server{
		Name:       &name,
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
		Module:     &Module{Name: "Power Supply"},
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("Fields.Names: %v\n", s.Fields().Names())

}
Output:

Fields.Names: [Name ID Enabled Count Password unexported Module]

func (StructFields) Parent

func (fields StructFields) Parent() *StructValue

Parent returns the related StructValue object (which is a level above StructFields).

type StructRows

type StructRows struct {
	StructValue // embedded copy and inherits all fields and methods.
	// contains filtered or unexported fields
}

StructRows represents a single row of a struct from a StructValue containing a slice of structs. If StructValue does not contain a slice of structs, StructRows cannot be initialized by contructor Rows. StructRows encapsulates high level functions around the element of slice of structs.

func (*StructRows) Close

func (r *StructRows) Close() error

Close closes the Rows, preventing further enumeration. If Next is called and returns false and there are no further result rows, the Rows are closed automatically and it will suffice to check the result of Err. Close is idempotent and does not affect the result of Err.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int32 `json:"count,omitempty"`
	}
	servers := []Server{
		{Count: 5},
		{Count: 6},
	}
	s, err := structs.New(&servers)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
	}
	rows, err := s.Rows()
	if err != nil {
		fmt.Printf("Rows[Error]: %v.\n", err)
	}
	for rows.Next() {
		fmt.Printf("struct row index: %d.\n", rows.Index())
	}
	err = rows.Close()
	if err != nil {
		fmt.Printf("Close[Error]: %v.\n", err)
	}
	fmt.Printf("struct row index: %d.\n", rows.Index())
	if err := rows.Err(); err != nil {
		fmt.Printf("Err[Error]: %v.\n", err)
	}

}
Output:

struct row index: 0.
struct row index: 1.
struct row index: -1.

func (*StructRows) Columns

func (r *StructRows) Columns() ([]string, error)

Columns returns the current struct field names. Columns returns an error if the rows are closed.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int32 `json:"count,omitempty"`
	}
	servers := []Server{
		{Count: 5},
		{Count: 6},
	}
	s, err := structs.New(&servers)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
	}
	rows, err := s.Rows()
	if err != nil {
		fmt.Printf("Rows[Error]: %v.\n", err)
	}
	cols, err := rows.Columns()
	if err != nil {
		fmt.Printf("Columns[Error]: %v.\n", err)
	} else {
		fmt.Printf("struct row column names: %s.\n", cols)
	}
	err = rows.Close()
	if err != nil {
		fmt.Printf("Close[Error]: %v.\n", err)
	}
	cols, err = rows.Columns()
	if err != nil {
		fmt.Printf("Columns[Error]: %v.\n", err)
	} else {
		fmt.Printf("struct row column names: %s.\n", cols)
	}
	if err := rows.Err(); err != nil {
		fmt.Printf("Err[Error]: %v.\n", err)
	}

}
Output:

struct row column names: [Count].
Columns[Error]: struct rows are closed.

func (*StructRows) Err

func (r *StructRows) Err() (err error)

Err returns the error, if any, that was encountered during iteration. Err may be called after an explicit or implicit Close.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int32 `json:"count,omitempty"`
	}
	servers := []Server{
		{Count: 5},
		{Count: 6},
	}
	s, err := structs.New(&servers)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
	}
	rows, err := s.Rows()
	if err != nil {
		fmt.Printf("Err[Error]: %v.\n", err)
	}
	defer rows.Close()
	fmt.Printf("struct row index: %d.\n", rows.Index())
	_ = rows.Field("InvalidName")
	if err := rows.Err(); err != nil {
		fmt.Printf("Err[Error]: %v.\n", err)
	}

}
Output:

struct row index: -1.
Err[Error]: invalid field name InvalidName.

func (*StructRows) Index

func (r *StructRows) Index() int

Index returns the index element in the slice of structs pointing to current struct. Index returns OutOfRange, i.e. -1, if the rows are closed.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int32 `json:"count,omitempty"`
	}
	servers := []Server{
		{Count: 5},
		{Count: 6},
	}
	s, err := structs.New(&servers)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
	}
	rows, err := s.Rows()
	if err != nil {
		fmt.Printf("Rows[Error]: %v.\n", err)
	}
	for rows.Next() {
		fmt.Printf("struct row index: %d.\n", rows.Index())
	}
	err = rows.Close()
	if err != nil {
		fmt.Printf("Close[Error]: %v.\n", err)
	}
	fmt.Printf("struct row index: %d.\n", rows.Index())
	if err := rows.Err(); err != nil {
		fmt.Printf("Err[Error]: %v.\n", err)
	}

}
Output:

struct row index: 0.
struct row index: 1.
struct row index: -1.

func (*StructRows) Len

func (r *StructRows) Len() int

Len returns the number elements in the slice of structs. Len returns OutOfRange, i.e. -1, if the rows are closed.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int32 `json:"count,omitempty"`
	}
	servers := []Server{
		{Count: 5},
		{Count: 6},
	}
	s, err := structs.New(&servers)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
	}
	rows, err := s.Rows()
	if err != nil {
		fmt.Printf("Rows[Error]: %v.\n", err)
	}
	fmt.Printf("struct number of rows: %d.\n", rows.Len())
	err = rows.Close()
	if err != nil {
		fmt.Printf("Close[Error]: %v.\n", err)
	}
	fmt.Printf("struct number of rows: %d.\n", rows.Len())
	if err := rows.Err(); err != nil {
		fmt.Printf("Err[Error]: %v.\n", err)
	}

}
Output:

struct number of rows: 2.
struct number of rows: -1.

func (*StructRows) MaxRow

func (r *StructRows) MaxRow() int

MaxRow returns the index of the lasr elements in the slice of structs. MaxRow returns OutOfRange, i.e. -1, if the rows are closed.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int32 `json:"count,omitempty"`
	}
	servers := []Server{
		{Count: 5},
		{Count: 6},
	}
	s, err := structs.New(&servers)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
	}
	rows, err := s.Rows()
	if err != nil {
		fmt.Printf("Rows[Error]: %v.\n", err)
	}
	fmt.Printf("struct last row index: %d.\n", rows.MaxRow())
	err = rows.Close()
	if err != nil {
		fmt.Printf("Close[Error]: %v.\n", err)
	}
	fmt.Printf("struct last row index: %d.\n", rows.MaxRow())
	if err := rows.Err(); err != nil {
		fmt.Printf("Err[Error]: %v.\n", err)
	}

}
Output:

struct last row index: 1.
struct last row index: -1.

func (*StructRows) Next

func (r *StructRows) Next() bool

Next prepares the next result row for reading an element from the slice of struct. It returns true on success, or false if there is no next result row or an error happened while preparing it. Err should be consulted to distinguish between the two cases.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int32 `json:"count,omitempty"`
	}
	servers := []Server{
		{Count: 5},
		{Count: 6},
	}
	s, err := structs.New(&servers)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
	}
	rows, err := s.Rows()
	if err != nil {
		fmt.Printf("Rows[Error]: %v.\n", err)
	}
	for rows.Next() {
		fmt.Printf("struct row index: %d.\n", rows.Index())
	}
	err = rows.Close()
	if err != nil {
		fmt.Printf("Close[Error]: %v.\n", err)
	}
	fmt.Printf("struct row index: %d.\n", rows.Index())
	if err := rows.Err(); err != nil {
		fmt.Printf("Err[Error]: %v.\n", err)
	}

}
Output:

struct row index: 0.
struct row index: 1.
struct row index: -1.

type StructValue

type StructValue struct {
	Parent *StructValue // Parent struct, if nested struct.
	Error  error        // Error added when struct could not be found.
	// contains filtered or unexported fields
}

StructValue is the representation of a Go struct powered by the Go reflection package. Its interface provides field getters, field setters and much more.

func IndirectStruct added in v1.0.5

func IndirectStruct(v reflect.Value) *StructValue

IndirectStruct finds the struct or structs in the interface dest.

Types   Description                     Example

T       a struct                        New(t)
*T      a pointer to a struct           New(&t)
[]T     a slice of struct               New([]T{t})
*[]T    a pointer to a slice of struct  New(&[]T{t})
[]*T    a slice of pointers to struct   New([]*T{&t})

Similar to utils.CanStruct(v)

func New

func New(dest interface{}, parents ...*StructValue) (*StructValue, error)

New returns a new StructValue initialized to the struct concrete value stored in the interface dest. New(nil) returns the StructValue with an error.

BUG(roninzo): the New method behaves unexpectidely when passing in an empty slice of pointers to structs.

StructValue.New

StructValue.findStruct(v, t) 		=> IndirectStruct
	StructValue.getElem(v, t) 		=> IndirectValueAndType
		utils.StructValueElem(v, t)

TODEL: New Load parent StructValue, if any.

TODEL: findStruct findStruct finds where the struct is inside the reflect value and type. By being chainable, findStruct uses withStruct to finalize successful completion and exit the switch case below, all in a one-liner, otherwise it returns the StructValue explictly at the end. See the Support paragraph in the documentation for more details.

TODEL: withStruct withStruct returns StructValue object after setting reflect.Value of struct found. By being chainable, withStruct can finalize StructValue and return it at the same time.

TODEL: getElem getElem returns the element or the first element of the reflection pointer value and type. It saves an errors inside StructValue if the type's Kind is not Array, Ptr, or Slice.

TODEL: appendKind appendKind appends reflect type t to the slice of kinds in StructValue. The first, it initialized kinds as a the slice of kinds.

TODEL: utils.StructValueElem StructValueElem follows the pointer v and returns the element it points to, for borth reflect value and reflect type, as well as nil error. If v is not a pointer or not a supported pointer, it returns zero-value reflect value and reflect type as well as an error.

MIGRATE: utils.CanStruct CanStruct returns true if reflect value represents a nested struct, else returns false.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type T struct {
		String string
		Uint   uint
		Bool   bool
		Int    int32
	}

	t := T{
		String: "Roninzo",
		Uint:   123456,
		Bool:   true,
		Int:    5,
	}

	s, err := structs.New(&t)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
		return
	}

	fmt.Printf("Name               : %v.\n", s.Name())
	fmt.Printf("Value of 1st field : %v.\n", s.Field(0).Value())
	fmt.Printf("Value of Uint      : %v.\n", s.Field("Uint").Value())
	fmt.Printf("Value of Int       : %v.\n", s.Field("Int").Value())
	fmt.Printf("Sprint: %s.\n", s.Sprint())

	err = s.Field("Uint").Set(uint(654321))
	if err != nil {
		fmt.Printf("Set[Error]: %v.\n", err)
	}

	err = s.Field("Int").Set(6)
	if err != nil {
		fmt.Printf("Set[Error]: %v.\n", err)
	}

	err = s.Field("Bool").Set(6)
	if err != nil {
		fmt.Printf("Set[Error]: %v.\n", err)
	}

	fmt.Printf("Value of String    : %s.\n", s.Field("String").String()) // syntax for %s verb
	fmt.Printf("Value of Uint      : %d.\n", s.Field("Uint").Uint())     // syntax for %d verb
	fmt.Printf("Value of Int       : %d.\n", s.Field("Int").Int())       // syntax for %d verb
	fmt.Printf("Sprint: %s.\n", s.Sprint())
	fmt.Printf("\nVerification       :\n")
	fmt.Printf("t.String           : %s.\n", t.String)
	fmt.Printf("t.Uint             : %d.\n", t.Uint)
	fmt.Printf("t.Int              : %d.\n", t.Int)

}
Output:

Name               : T.
Value of 1st field : Roninzo.
Value of Uint      : 123456.
Value of Int       : 5.
Sprint: {
 	"String": "Roninzo",
 	"Uint": 123456,
 	"Bool": true,
 	"Int": 5
 }.
Set[Error]: wrong kind of value for field T.Bool. got: "int" want: "bool".
Value of String    : Roninzo.
Value of Uint      : 654321.
Value of Int       : 6.
Sprint: {
 	"String": "Roninzo",
 	"Uint": 654321,
 	"Bool": true,
 	"Int": 6
 }.

Verification       :
t.String           : Roninzo.
t.Uint             : 654321.
t.Int              : 6.

func (*StructValue) CanSet

func (s *StructValue) CanSet() bool

CanSet reports whether the value of StructValue can be changed. A StructValue can be changed only if it is addressable and was not obtained by the use of unexported struct fields. If CanSet returns false, calling Set or any type-specific setter (e.g., SetBool, SetInt) will panic.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name     string   `json:"name,omitempty"`
		ID       uint     `json:"id,omitempty"`
		Enabled  bool     `json:"enabled,omitempty"`
		Count    int32    `json:"count,omitempty"`
		Password string   `json:"-"`
		Program  *Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  &program,
	}

	s1, _ := structs.New(&server)
	s2, _ := structs.New(server)

	fmt.Printf("CanSet: %v\n", s1.CanSet())
	fmt.Printf("CanSet: %v\n", s2.CanSet())

}
Output:

CanSet: true
CanSet: false

func (*StructValue) Contains

func (s *StructValue) Contains(dest interface{}) int

Contains returns index field of struct inside interface dest. Unexported struct fields will be neglected.

func (*StructValue) Debug

func (s *StructValue) Debug() string

Debug dumps the StructValue object itself as json string.

func (*StructValue) Defaults added in v1.0.5

func (s *StructValue) Defaults() error

Defaults initializes struct from inline default struct tags. Unsettable and zero-value fields will be neglected.

func (*StructValue) Diff added in v1.0.3

func (s *StructValue) Diff(c *StructValue) (map[string]interface{}, error)

Diff returns the differences in field values between two StructValue.

Example
package main

import (
	"fmt"
	"sort"
	"time"

	"github.com/pkg/errors"
	"github.com/roninzo/pointers"
	"github.com/roninzo/structs"
)

func main() {
	s1, err := structs.New(&structV)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
		return
	}

	s2, err := structs.New(&structX)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
		return
	}

	diffs, err := s2.Diff(s1)
	if err != nil {
		fmt.Printf("Diff[Error]: %v.\n", err)
		return
	}

	keys := make([]string, len(diffs))
	i := 0
	for key := range diffs {
		keys[i] = key
		i++
	}
	sort.Strings(keys)
	for _, key := range keys {
		fmt.Printf("Diff[%s]: %+v.\n", key, structs.SprintCompact(diffs[key]))
	}

}

type structTest struct {
	String          string                 `json:"string,omitempty"`
	Bool            bool                   `json:"bool,omitempty"`
	Int             int                    `json:"int,omitempty"`
	Uint            uint                   `json:"uint,omitempty"`
	Float           float32                `json:"float,omitempty"`
	Complex         complex128             `json:"complex,omitempty"`
	Bytes           []byte                 `json:"bytes,omitempty"`
	Interface       interface{}            `json:"interface,omitempty"`
	Error           error                  `json:"error,omitempty"`
	Time            time.Time              `json:"time,omitempty"`
	Duration        time.Duration          `json:"duration,omitempty"`
	NestedStruct    structNested           `json:"nested_struct,omitempty"`
	PtrString       *string                `json:"pointer_string,omitempty"`
	PtrBool         *bool                  `json:"pointer_bool,omitempty"`
	PtrInt          *int                   `json:"pointer_int,omitempty"`
	PtrUint         *uint                  `json:"pointer_uint,omitempty"`
	PtrFloat        *float32               `json:"pointer_float,omitempty"`
	PtrComplex      *complex128            `json:"pointer_complex,omitempty"`
	PtrError        *error                 `json:"pointer_error,omitempty"`
	PtrTime         *time.Time             `json:"pointer_time,omitempty"`
	PtrDuration     *time.Duration         `json:"pointer_duration,omitempty"`
	PtrNestedStruct *structNested          `json:"pointer_nested_struct,omitempty"`
	MapString       map[string]string      `json:"map_string,omitempty"`
	MapBool         map[string]bool        `json:"map_bool,omitempty"`
	MapInt          map[string]int         `json:"mapint,omitempty"`
	MapUint         map[string]uint        `json:"map_uint,omitempty"`
	MapFloat        map[string]float32     `json:"map_float,omitempty"`
	MapComplex      map[string]complex128  `json:"map_complex,omitempty"`
	MapInterface    map[string]interface{} `json:"map_interface,omitempty"`
	SliceString     []string               `json:"slice_string,omitempty"`
	SliceBool       []bool                 `json:"slice_bool,omitempty"`
	SliceInt        []int                  `json:"slice_int,omitempty"`
	SliceUint       []uint                 `json:"slice_uint,omitempty"`
	SliceFloat      []float32              `json:"slice_float,omitempty"`
	SliceComplex    []complex128           `json:"slice_complex,omitempty"`
	SliceInterface  []interface{}          `json:"slice_interface,omitempty"`
	SlicePtrString  []*string              `json:"slice_pointer_string,omitempty"`
	SlicePtrBool    []*bool                `json:"slice_pointer_bool,omitempty"`
	SlicePtrInt     []*int                 `json:"slice_pointer_int,omitempty"`
	SlicePtrUint    []*uint                `json:"slice_pointer_uint,omitempty"`
	SlicePtrFloat   []*float32             `json:"slice_pointer_float,omitempty"`
	SlicePtrComplex []*complex128          `json:"slice_pointer_complex,omitempty"`
	Hidden          string                 `json:"-"`
	unexported      bool
}

type structNested struct {
	Uint   uint   `json:"uint,omitempty"`
	String string `json:"string,omitempty"`
}

var structV structTest = structTest{
	String:          "Roninzo",
	Bool:            true,
	Int:             8,
	Uint:            uint(123456),
	Float:           1922.50,
	Complex:         complex(22, 50),
	Bytes:           []byte("Hello world"),
	Interface:       "anything",
	Error:           errors.New("rows not found"),
	Time:            time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC),
	Duration:        5 * time.Second,
	NestedStruct:    structNested{Uint: 122334, String: "Apache"},
	PtrString:       pointers.String("Roninzo"),
	PtrBool:         pointers.Bool(true),
	PtrInt:          pointers.Int(8),
	PtrUint:         pointers.Uint(uint(123456)),
	PtrFloat:        pointers.Float32(1922.50),
	PtrComplex:      pointers.Complex128(complex(22, 50)),
	PtrError:        pointers.Error(errors.New("rows not found")),
	PtrTime:         pointers.Time(time.Date(2021, time.August, 3, 16, 44, 46, 0, time.UTC)),
	PtrDuration:     pointers.Duration(5 * time.Second),
	PtrNestedStruct: &structNested{Uint: 122334, String: "Apache"},
	MapString:       map[string]string{"A": "one", "B": "two", "C": "three"},
	MapBool:         map[string]bool{"A": true, "B": false},
	MapInt:          map[string]int{"A": 1, "B": 2, "C": 3},
	MapUint:         map[string]uint{"A": uint(1), "B": uint(2), "C": uint(3)},
	MapFloat:        map[string]float32{"A": 1.1, "B": 1.2, "C": 1.3},
	MapComplex:      map[string]complex128{"A": complex(1, 1), "B": complex(1, 2), "C": complex(1, 3)},
	MapInterface:    map[string]interface{}{"A": 1, "B": "two", "C": 3.0},
	SliceString:     []string{"one", "two", "three"},
	SliceBool:       []bool{true, false},
	SliceInt:        []int{1, 2, 3},
	SliceUint:       []uint{uint(1), uint(2), uint(3)},
	SliceFloat:      []float32{1.1, 1.2, 1.3},
	SliceComplex:    []complex128{complex(1, 1), complex(1, 2), complex(1, 3)},
	SliceInterface:  []interface{}{1, "two", 3.0},
	SlicePtrString:  []*string{pointers.String("one"), pointers.String("two"), pointers.String("three")},
	SlicePtrBool:    []*bool{pointers.Bool(true), pointers.Bool(false)},
	SlicePtrInt:     []*int{pointers.Int(1), pointers.Int(2), pointers.Int(3)},
	SlicePtrUint:    []*uint{pointers.Uint(uint(1)), pointers.Uint(uint(2)), pointers.Uint(uint(3))},
	SlicePtrFloat:   []*float32{pointers.Float32(1.1), pointers.Float32(1.2), pointers.Float32(1.3)},
	SlicePtrComplex: []*complex128{pointers.Complex128(complex(1, 1)), pointers.Complex128(complex(1, 2)), pointers.Complex128(complex(1, 3))},
	Hidden:          "abcdefg",
	unexported:      true,
}

var structX structTest = structTest{
	String:          "ozninoR",
	Bool:            false,
	Int:             3,
	Uint:            uint(654321),
	Float:           7622.50,
	Complex:         complex(-67, -42),
	Bytes:           []byte("Bye bye world"),
	Interface:       3.99,
	Error:           errors.New("not compliant"),
	Time:            time.Date(2021, time.August, 31, 14, 11, 11, 0, time.UTC),
	Duration:        30 * time.Second,
	NestedStruct:    structNested{Uint: 443211, String: "Microsoft IIS"},
	PtrString:       pointers.String("ozninoR"),
	PtrBool:         pointers.Bool(false),
	PtrInt:          pointers.Int(3),
	PtrUint:         pointers.Uint(uint(654321)),
	PtrFloat:        pointers.Float32(7622.50),
	PtrComplex:      pointers.Complex128(complex(-67, -42)),
	PtrError:        pointers.Error(errors.New("not compliant")),
	PtrTime:         pointers.Time(time.Date(2021, time.August, 31, 14, 11, 11, 0, time.UTC)),
	PtrDuration:     pointers.Duration(30 * time.Second),
	PtrNestedStruct: &structNested{Uint: 443211, String: "Microsoft IIS"},
	MapString:       map[string]string{"D": "four", "E": "five", "F": "six"},
	MapBool:         map[string]bool{"D": false, "E": true},
	MapInt:          map[string]int{"D": 4, "E": 5, "F": 6},
	MapUint:         map[string]uint{"D": uint(4), "E": uint(5), "F": uint(6)},
	MapFloat:        map[string]float32{"D": 1.4, "E": 1.5, "F": 1.6},
	MapComplex:      map[string]complex128{"D": complex(1, 4), "E": complex(1, 5), "F": complex(1, 6)},
	MapInterface:    map[string]interface{}{"D": 4, "E": "five", "F": 6.0},
	SliceString:     []string{"four", "five", "six"},
	SliceBool:       []bool{false, true},
	SliceInt:        []int{4, 5, 6},
	SliceUint:       []uint{uint(4), uint(5), uint(6)},
	SliceFloat:      []float32{1.4, 1.5, 1.6},
	SliceComplex:    []complex128{complex(1, 4), complex(1, 5), complex(1, 6)},
	SliceInterface:  []interface{}{4, "five", 6.0},
	SlicePtrString:  []*string{pointers.String("four"), pointers.String("five"), pointers.String("six")},
	SlicePtrBool:    []*bool{pointers.Bool(false), pointers.Bool(true)},
	SlicePtrInt:     []*int{pointers.Int(4), pointers.Int(5), pointers.Int(6)},
	SlicePtrUint:    []*uint{pointers.Uint(uint(4)), pointers.Uint(uint(5)), pointers.Uint(uint(6))},
	SlicePtrFloat:   []*float32{pointers.Float32(1.4), pointers.Float32(1.5), pointers.Float32(1.6)},
	SlicePtrComplex: []*complex128{pointers.Complex128(complex(1, 4)), pointers.Complex128(complex(1, 5)), pointers.Complex128(complex(1, 6))},
	Hidden:          "gfedcba",
	unexported:      false,
}
Output:

Diff[bool]: false.
Diff[bytes]: "QnllIGJ5ZSB3b3JsZA==".
Diff[complex]: json: unsupported type: complex128.
Diff[duration]: 30000000000.
Diff[error]: "not compliant".
Diff[float]: 7622.5.
Diff[hidden]: "gfedcba".
Diff[int]: 3.
Diff[interface]: 3.99.
Diff[map_bool]: {"D":false,"E":true}.
Diff[map_complex]: json: unsupported type: complex128.
Diff[map_float]: {"D":1.4,"E":1.5,"F":1.6}.
Diff[map_interface]: {"D":4,"E":"five","F":6}.
Diff[map_string]: {"D":"four","E":"five","F":"six"}.
Diff[map_uint]: {"D":4,"E":5,"F":6}.
Diff[mapint]: {"D":4,"E":5,"F":6}.
Diff[nested_struct]: {"uint":443211,"string":"Microsoft IIS"}.
Diff[pointer_bool]: false.
Diff[pointer_complex]: json: unsupported type: complex128.
Diff[pointer_duration]: 30000000000.
Diff[pointer_error]: "not compliant".
Diff[pointer_float]: 7622.5.
Diff[pointer_int]: 3.
Diff[pointer_nested_struct]: {"uint":443211,"string":"Microsoft IIS"}.
Diff[pointer_string]: "ozninoR".
Diff[pointer_time]: "2021-08-31T14:11:11Z".
Diff[pointer_uint]: 654321.
Diff[slice_bool]: [false,true].
Diff[slice_complex]: json: unsupported type: complex128.
Diff[slice_float]: [1.4,1.5,1.6].
Diff[slice_int]: [4,5,6].
Diff[slice_interface]: [4,"five",6].
Diff[slice_pointer_bool]: [false,true].
Diff[slice_pointer_complex]: json: unsupported type: complex128.
Diff[slice_pointer_float]: [1.4,1.5,1.6].
Diff[slice_pointer_int]: [4,5,6].
Diff[slice_pointer_string]: ["four","five","six"].
Diff[slice_pointer_uint]: [4,5,6].
Diff[slice_string]: ["four","five","six"].
Diff[slice_uint]: [4,5,6].
Diff[string]: "ozninoR".
Diff[time]: "2021-08-31T14:11:11Z".
Diff[uint]: 654321.

func (*StructValue) Err

func (s *StructValue) Err() (err error)

Err gets error from StructValue, then resets internal error.

func (*StructValue) Field

func (s *StructValue) Field(dest interface{}) *StructField

Field returns nil or one of the fields of the struct that matches argument dest. Its argument dest can be the name or the index of the field. Field(nil) returns nil and adds an error to StructValue.

NOTE: Field is an alias to either the getFieldByName or the getFieldByIndex method.

TODO: getFieldByIndex ability to access nested field names using []int as index.

e.g.: [1, 3, 1] <=> v.Field(1).Field(3).Field(1)

TODO: getFieldByName ability to parse nested field names inside n.

e.g.: "Struct.Nested.String" <=> v.FieldByName("Struct").FieldByName("Nested").FieldByName("String")
Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	f1 := s.Field(0)
	f2 := s.Field("Enabled")

	fmt.Printf("Field.Name: %v\n", f1.Name())
	fmt.Printf("Field.Value: %v\n", f1.Value())
	fmt.Printf("Field.Name: %v\n", f2.Name())
	fmt.Printf("Field.Value: %v\n", f2.Value())

}
Output:

Field.Name: Name
Field.Value: Roninzo
Field.Name: Enabled
Field.Value: true

func (*StructValue) Fields

func (s *StructValue) Fields() StructFields

Fields returns all the fields of the struct in a slice. This method is not recursive, which means that nested structs must be dealt with explicitly.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name       string `json:"name,omitempty"`
		ID         uint   `json:"id,omitempty"`
		Enabled    bool   `json:"enabled,omitempty"`
		Count      int32  `json:"count,omitempty"`
		Password   string `json:"-"`
		unexported bool
	}

	server := Server{
		Name:       "Roninzo",
		ID:         123456,
		Enabled:    true,
		Count:      0,
		Password:   "abcdefg",
		unexported: true,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("NumField: %d\n", s.NumField())

	fields := s.Fields()
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("Fields.Names: %v\n", fields.Names())

}
Output:

NumField: 6
Fields.Names: [Name ID Enabled Count Password unexported]

func (*StructValue) FindStruct

func (s *StructValue) FindStruct(name string) *StructValue

FindStruct recursively finds and returns the StructValue object matching provided name, i.e.: the name of struct desired.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name     string   `json:"name,omitempty"`
		ID       uint     `json:"id,omitempty"`
		Enabled  bool     `json:"enabled,omitempty"`
		Count    int32    `json:"count,omitempty"`
		Password string   `json:"-"`
		Program  *Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  &program,
	}

	s1, _ := structs.New(&server)
	s2 := s1.FindStruct("Program")

	fmt.Printf("Program.Name: %v\n", s2.Name())
	fmt.Printf("Program.Value: %v\n", s2.Value())

}
Output:

Program.Name: Program
Program.Value: {Apache}

func (*StructValue) Forward

func (s *StructValue) Forward(c *StructValue) error

Forward loops through destination fields of struct s and set their values to the corresponding fields from c. Zero-value fields from c will be neglected. Unsettable struct fields will be neglected.

func (*StructValue) FullName added in v1.0.5

func (s *StructValue) FullName() string

FullName returns the same as the Name method, unless StructValue is a nested struct. When dealing with a nested struct, parent struct names are looked up and concatenated to the response recursively all the way to the top level struct.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name     string   `json:"name,omitempty"`
		ID       uint     `json:"id,omitempty"`
		Enabled  bool     `json:"enabled,omitempty"`
		Count    int32    `json:"count,omitempty"`
		Password string   `json:"-"`
		Program  *Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  &program,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	p := s.FindStruct("Program")

	fmt.Printf("FullName: %v\n", s.FullName())
	fmt.Printf("FullName: %v\n", p.FullName())

}
Output:

FullName: Server
FullName: Server.Program

func (*StructValue) HasField

func (s *StructValue) HasField(dest interface{}, arg interface{}) (bool, error)

HasField returns true if struct dest has a field called the same as argument name.

func (*StructValue) HasNested

func (s *StructValue) HasNested() bool

HasNested returns true if struct has one or more nested struct within the root struct. HasNested returns false if none of the fields is sub-struct.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name     string   `json:"name,omitempty"`
		ID       uint     `json:"id,omitempty"`
		Enabled  bool     `json:"enabled,omitempty"`
		Count    int32    `json:"count,omitempty"`
		Password string   `json:"-"`
		Program  *Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  &program,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	p, err := structs.New(&program)
	if p.Error != nil {
		fmt.Printf("Error: %s\n", p.Error)
	}

	fmt.Printf("Server.HasNested: %v\n", s.HasNested())
	fmt.Printf("Program.HasNested: %v\n", p.HasNested())

}
Output:

Server.HasNested: true
Program.HasNested: false

func (*StructValue) HasZero

func (s *StructValue) HasZero() bool

HasZero returns true if one or more struct fields are of zero value. Unexported struct fields will be neglected.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name     string `json:"name,omitempty"`
		ID       uint   `json:"id,omitempty"`
		Enabled  bool   `json:"enabled,omitempty"`
		Count    int32  `json:"count,omitempty"`
		Password string `json:"-"`
	}

	server := Server{
		Name:     "Roninzo",
		ID:       0, // zero-value
		Enabled:  true,
		Count:    5,
		Password: "abcdefg",
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("HasZero: %v\n", s.HasZero())

	server = Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    5,
		Password: "abcdefg",
	}

	s, err = structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("HasZero: %v\n", s.HasZero())

}
Output:

HasZero: true
HasZero: false

func (*StructValue) Import

func (s *StructValue) Import(c *StructValue) error

Import loops through destination fields of struct s and set their values to the corresponding fields from c. Usually, s is a trim-down version of c. Unsettable struct fields will be neglected.

func (*StructValue) IndirectValues added in v1.0.5

func (s *StructValue) IndirectValues() (values []reflect.Value)

IndirectValues returns the values of the struct as a slice of reflect Values recursively.

Example
package main

import (
	"fmt"

	"github.com/roninzo/pointers"
	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name *string `json:"name,omitempty"`
	}

	type Server struct {
		Name       *string  `json:"name,omitempty"`
		ID         *uint    `json:"id,omitempty"`
		Enabled    *bool    `json:"enabled,omitempty"`
		Count      *int     `json:"count,omitempty"`
		Program    *Program `json:"program,omitempty"`
		Password   *string  `json:"-"`
		unexported *bool
	}

	pointers.NullifyZeroValues = false

	program := Program{
		Name: pointers.String("Apache"),
	}

	server := Server{
		Name:       pointers.String("Roninzo"),
		ID:         pointers.Uint(123456),
		Enabled:    pointers.Bool(true),
		Count:      pointers.Int(0),
		Program:    &program,
		Password:   pointers.String("abcdefg"),
		unexported: pointers.Bool(true),
	}

	pointers.NullifyZeroValues = true

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v.\n", err)
	}

	// json struct tag omits Password and Count
	for i, value := range s.IndirectValues() {
		fmt.Printf("IndirectValues[%d]: %v.\n", i, value)
	}

}
Output:

IndirectValues[0]: Roninzo.
IndirectValues[1]: 123456.
IndirectValues[2]: true.
IndirectValues[3]: 0.
IndirectValues[4]: Apache.
IndirectValues[5]: abcdefg.
IndirectValues[6]: true.

func (*StructValue) IsNested

func (s *StructValue) IsNested() bool

IsNested returns true if struct is a nested struct within the root struct. IsNested returns false if StructValue is the top level struct.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name     string   `json:"name,omitempty"`
		ID       uint     `json:"id,omitempty"`
		Enabled  bool     `json:"enabled,omitempty"`
		Count    int32    `json:"count,omitempty"`
		Password string   `json:"-"`
		Program  *Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  &program,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	p := s.FindStruct("Program")

	fmt.Printf("Server.IsNested: %v\n", s.IsNested())
	fmt.Printf("Program.IsNested: %v\n", p.IsNested())

}
Output:

Server.IsNested: false
Program.IsNested: true

func (*StructValue) IsValid

func (s *StructValue) IsValid() bool

IsValid returns true if the struct was found. It is so when StructValue represents a reflect value.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name    string
		ID      uint
		Enabled bool
		Count   int32
	}

	server := Server{
		Name:    "Roninzo",
		ID:      123456,
		Enabled: true,
		Count:   5,
	}

	s, err := structs.New(nil)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	} else {
		fmt.Printf("IsValid: %v\n", s.IsValid())
	}

	s, err = structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	} else {
		fmt.Printf("IsValid: %v\n", s.IsValid())
	}

}
Output:

Error: invalid concrete value; want: "struct" or "ptr" or "slice", got: <nil>
IsValid: true

func (*StructValue) IsZero

func (s *StructValue) IsZero() bool

IsZero returns true if all struct fields are of zero value. Unexported struct fields will be neglected.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name     string `json:"name,omitempty"`
		ID       uint   `json:"id,omitempty"`
		Enabled  bool   `json:"enabled,omitempty"`
		Count    int32  `json:"count,omitempty"`
		Password string `json:"-"`
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("IsZero: %v\n", s.IsZero())

	server = Server{
		Name:     "",
		ID:       0,
		Enabled:  false,
		Count:    0,
		Password: "",
	}

	s, err = structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("IsZero: %v\n", s.IsZero())

}
Output:

IsZero: false
IsZero: true

func (*StructValue) Kind

func (s *StructValue) Kind() reflect.Kind

Kind returns the struct reflect kind, or the last kind identified when the struct could not be found.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name    string
		ID      uint
		Enabled bool
		Count   int32
	}

	server := Server{
		Name:    "Roninzo",
		ID:      123456,
		Enabled: true,
		Count:   5,
	}

	s, err := structs.New(nil)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	if s != nil {
		fmt.Printf("Kind: %v\n", s.Kind())
	}

	s, err = structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("Kind: %v\n", s.Kind())

}
Output:

Error: invalid concrete value; want: "struct" or "ptr" or "slice", got: <nil>
Kind: struct

func (*StructValue) MapFunc

func (s *StructValue) MapFunc(handler func(reflect.Value) error) (*StructValue, error)

MapFunc maps struct with func handler.

func (*StructValue) Multiple

func (s *StructValue) Multiple() bool

Multiple reports whether the value of StructValue is a slice of structs. If Multiple returns false, either the struct was not found or it was not part of a slice of them.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name     string `json:"name,omitempty"`
		ID       uint   `json:"id,omitempty"`
		Enabled  bool   `json:"enabled,omitempty"`
		Count    int32  `json:"count,omitempty"`
		Password string `json:"-"`
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
	}

	s1, _ := structs.New(&server)
	s2, _ := structs.New([]*Server{&server})

	fmt.Printf("Multiple: %v\n", s1.Multiple())
	fmt.Printf("Multiple: %v\n", s2.Multiple())

}
Output:

Multiple: false
Multiple: true

func (*StructValue) Name

func (s *StructValue) Name() string

Name returns the name of the struct. When the struct was not found, it returns zero-value string.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name    string
		ID      uint
		Enabled bool
		Count   int32
	}

	server := Server{
		Name:    "Roninzo",
		ID:      123456,
		Enabled: true,
		Count:   5,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("Name: %v\n", s.Name())

}
Output:

Name: Server

func (*StructValue) NumField

func (s *StructValue) NumField() int

NumField returns the number of fields in the struct. This method is not recursive, which means that nested structs must be dealt with explicitly.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name     string `json:"name,omitempty"`
		ID       uint   `json:"id,omitempty"`
		Enabled  bool   `json:"enabled,omitempty"`
		Count    int32  `json:"count,omitempty"`
		Password string `json:"-"`
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("NumField: %v\n", s.NumField())

}
Output:

NumField: 5

func (*StructValue) Path

func (s *StructValue) Path() string

Path returns a comma separated string of reflect.Kind.String describing where the struct was found inside the interface input of the New method.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name     string `json:"name,omitempty"`
		ID       uint   `json:"id,omitempty"`
		Enabled  bool   `json:"enabled,omitempty"`
		Count    int32  `json:"count,omitempty"`
		Password string `json:"-"`
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    5,
		Password: "abcdefg",
	}

	s1, _ := structs.New(server)
	s2, _ := structs.New(&server)
	s3, _ := structs.New([]Server{server})
	s4, _ := structs.New(&[]Server{server})
	s5, _ := structs.New([]*Server{&server})

	fmt.Printf("Path: %v\n", s1.Path())
	fmt.Printf("Path: %v\n", s2.Path())
	fmt.Printf("Path: %v\n", s3.Path())
	fmt.Printf("Path: %v\n", s4.Path())
	fmt.Printf("Path: %v\n", s5.Path())

}
Output:

Path: struct
Path: ptr,struct
Path: slice,struct
Path: ptr,slice,struct
Path: slice,ptr,struct

func (*StructValue) Rows

func (s *StructValue) Rows() (*StructRows, error)

Rows returns an iterator, for a slice of structs. Rows returns nil if there was an error.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int32 `json:"count,omitempty"`
	}

	servers := []Server{
		{Count: 5},
		{Count: 6},
	}

	s, err := structs.New(&servers)
	if err != nil {
		fmt.Printf("New: %v.\n", err)
	}

	rows, err := s.Rows()
	if err != nil {
		fmt.Printf("Rows[Error]: %v.\n", err)
	}
	defer rows.Close()

	cols, err := rows.Columns()
	if err != nil {
		fmt.Printf("Columns[Error]: %v.\n", err)
	}
	fmt.Printf("Row: %s.\n", s.Sprint())
	fmt.Printf("StructValue: %s.\n", s.Debug())
	fmt.Printf("Len: %d.\n", rows.Len())
	fmt.Printf("MaxRow: %d.\n", rows.MaxRow())
	fmt.Printf("Columns: %v.\n", cols)

	for rows.Next() {
		f := rows.Field("Count")
		fmt.Printf("[%d] %s: %d.\n", rows.Index(), f.Name(), f.Int())
		c := f.Int()
		err := f.Set(c * 10)
		if err != nil {
			fmt.Printf("Set[Error]: %v.\n", err)
		}
		fmt.Printf("[%d] %s: %d.\n", rows.Index(), f.Name(), f.Int())
	}

	if err := rows.Err(); err != nil {
		fmt.Printf("Err[Error]: %v.\n", err)
	}

	fmt.Println("Verification:")
	fmt.Printf("servers[0].Count: %d.\n", servers[0].Count)
	fmt.Printf("servers[1].Count: %d.\n", servers[1].Count)

}
Output:

Row: {
 	"count": 5
 }.
StructValue: {
 	"value": {
 		"count": 5
 	},
 	"rows": [
 		{
 			"count": 5
 		},
 		{
 			"count": 6
 		}
 	],
 	"max_row": 2,
 	"kinds": "ptr,slice,struct",
 	"fields": {
 		"0": "Count"
 	},
 	"parent": "",
 	"error": null
 }.
Len: 2.
MaxRow: 1.
Columns: [Count].
[0] Count: 5.
[0] Count: 50.
[1] Count: 6.
[1] Count: 60.
Verification:
servers[0].Count: 50.
servers[1].Count: 60.
Example (Empty)
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int32 `json:"count,omitempty"`
	}

	servers := []Server{}

	s, err := structs.New(&servers)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
	}

	rows, err := s.Rows()
	if err != nil {
		fmt.Printf("Rows[Error]: %v.\n", err)
	}
	if rows != nil {
		fmt.Printf("Rows: %v.\n", rows)
	}

}
Output:

Rows[Error]: struct rows not found.
Example (NotMultiple)
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Count int32 `json:"count,omitempty"`
	}

	server := Server{
		Count: 5,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("New[Error]: %v.\n", err)
	}

	rows, err := s.Rows()
	if err != nil {
		fmt.Printf("Rows[Error]: %v.\n", err)
	}
	if rows != nil {
		fmt.Printf("Rows: %v.\n", rows)
	}

}
Output:

Rows[Error]: structs not found.

func (*StructValue) Sprint added in v1.0.1

func (s *StructValue) Sprint() string

Sprint returns struct as a string, similar to the Values method, but in a json indented format. When the struct was not found, it returns zero-value string. Unexported struct fields will be neglected.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name     string  `json:"name,omitempty"`
		ID       uint    `json:"id,omitempty"`
		Enabled  bool    `json:"enabled,omitempty"`
		Count    int32   `json:"count,omitempty"`
		Password string  `json:"-"`
		Program  Program `json:"program,omitempty"`
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  program,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	// json struct tag omits Password and Count
	fmt.Printf("Sprint: %s\n", s.Sprint())

}
Output:

Sprint: {
 	"name": "Roninzo",
 	"id": 123456,
 	"enabled": true,
 	"program": {
 		"name": "Apache"
 	}
 }

func (*StructValue) Type

func (s *StructValue) Type() reflect.Type

Type returns the type struct name, including the name of package, such as "structs.T".

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name    string
		ID      uint
		Enabled bool
		Count   int32
	}

	server := Server{
		Name:    "Roninzo",
		ID:      123456,
		Enabled: true,
		Count:   5,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("Type: %v\n", s.Type())

}
Output:

Type: structs_test.Server

func (*StructValue) Value

func (s *StructValue) Value() (v reflect.Value)

Value returns the reflect value of the struct when the struct was found, else it returns zero-value reflect value.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Server struct {
		Name    string
		ID      uint
		Enabled bool
		Count   int32
	}

	server := Server{
		Name:    "Roninzo",
		ID:      123456,
		Enabled: true,
		Count:   5,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	fmt.Printf("Value: %v\n", s.Value())

}
Output:

Value: {Roninzo 123456 true 5}

func (*StructValue) Values

func (s *StructValue) Values() (values []reflect.Value)

Values returns the values of the struct as a slice of interfaces recursively. Unexported struct fields will be neglected.

Example
package main

import (
	"fmt"

	"github.com/roninzo/structs"
)

func main() {
	type Program struct {
		Name string `json:"name,omitempty"`
	}

	type Server struct {
		Name       string  `json:"name,omitempty"`
		ID         uint    `json:"id,omitempty"`
		Enabled    bool    `json:"enabled,omitempty"`
		Count      int32   `json:"count,omitempty"`
		Password   string  `json:"-"`
		Program    Program `json:"program,omitempty"`
		unexported bool
	}

	program := Program{
		Name: "Apache",
	}

	server := Server{
		Name:     "Roninzo",
		ID:       123456,
		Enabled:  true,
		Count:    0,
		Password: "abcdefg",
		Program:  program,
	}

	s, err := structs.New(&server)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}

	// json struct tag omits Password and Count
	for i, value := range s.Values() {
		fmt.Printf("Values[%d]: %v\n", i, value)
	}

}
Output:

Values[0]: Roninzo
Values[1]: 123456
Values[2]: true
Values[3]: 0
Values[4]: abcdefg
Values[5]: Apache

Notes

Bugs

  • Sprint uses json marshaling which does not support complex types (complex64/complex128).

  • the MapFunc method argument dest is also changed. should that be the case?

  • the New method behaves unexpectidely when passing in an empty slice of pointers to structs.

    StructValue.New

    StructValue.findStruct(v, t) => IndirectStruct
    StructValue.getElem(v, t) => IndirectValueAndType
    utils.StructValueElem(v, t)
    

    TODEL: New Load parent StructValue, if any.

    TODEL: findStruct findStruct finds where the struct is inside the reflect value and type. By being chainable, findStruct uses withStruct to finalize successful completion and exit the switch case below, all in a one-liner, otherwise it returns the StructValue explictly at the end. See the Support paragraph in the documentation for more details.

    TODEL: withStruct withStruct returns StructValue object after setting reflect.Value of struct found. By being chainable, withStruct can finalize StructValue and return it at the same time.

    TODEL: getElem getElem returns the element or the first element of the reflection pointer value and type. It saves an errors inside StructValue if the type's Kind is not Array, Ptr, or Slice.

    TODEL: appendKind appendKind appends reflect type t to the slice of kinds in StructValue. The first, it initialized kinds as a the slice of kinds.

    TODEL: utils.StructValueElem StructValueElem follows the pointer v and returns the element it points to, for borth reflect value and reflect type, as well as nil error. If v is not a pointer or not a supported pointer, it returns zero-value reflect value and reflect type as well as an error.

    MIGRATE: utils.CanStruct CanStruct returns true if reflect value represents a nested struct, else returns false.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL