Top Related Projects
Go library for decoding generic map values into native Go structures and vice versa.
:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
Copier for golang, copy value from struct to struct and more
Mergo: merging Go structs and maps since 2013
safe and easy casting from one type to another in Go
Quick Overview
fatih/structs is a Go package that allows you to manipulate and extract data from structs. It provides a simple and intuitive way to convert Go structs into maps, fill structs with data from maps, and perform various operations on struct fields without using reflection directly.
Pros
- Simplifies working with structs by abstracting away complex reflection code
- Provides a convenient way to convert structs to maps and vice versa
- Supports nested structs and custom field tags
- Lightweight and easy to integrate into existing projects
Cons
- May have a slight performance overhead compared to direct struct manipulation
- Limited support for some advanced Go features like interfaces
- Requires careful usage to avoid runtime panics when dealing with unexported fields
- Not actively maintained (last commit was in 2019)
Code Examples
- Converting a struct to a map:
type Person struct {
Name string
Age int
}
person := Person{Name: "John Doe", Age: 30}
personMap := structs.Map(person)
fmt.Printf("%+v\n", personMap)
// Output: map[Name:John Doe Age:30]
- Filling a struct with data from a map:
type User struct {
ID int
Name string
}
userData := map[string]interface{}{"ID": 1, "Name": "Alice"}
user := &User{}
structs.Decode(userData, user)
fmt.Printf("%+v\n", user)
// Output: &{ID:1 Name:Alice}
- Checking if a struct is zero-valued:
type Empty struct{}
type NonEmpty struct {
Value string
}
fmt.Println(structs.IsZero(Empty{})) // true
fmt.Println(structs.IsZero(NonEmpty{})) // true
fmt.Println(structs.IsZero(NonEmpty{Value: "Hello"})) // false
Getting Started
To use fatih/structs in your Go project, follow these steps:
-
Install the package:
go get github.com/fatih/structs
-
Import the package in your Go code:
import "github.com/fatih/structs"
-
Start using the package functions:
type MyStruct struct { Field1 string Field2 int } s := MyStruct{Field1: "Hello", Field2: 42} m := structs.Map(s) fmt.Printf("%+v\n", m)
Competitor Comparisons
Go library for decoding generic map values into native Go structures and vice versa.
Pros of mapstructure
- More flexible decoding options, including custom decoders and weak type conversion
- Better support for nested structures and slices
- Ability to decode into existing struct instances
Cons of mapstructure
- Slightly more complex API compared to structs
- May have a steeper learning curve for beginners
- Less focus on struct reflection and field manipulation
Code Comparison
mapstructure:
type Person struct {
Name string
Age int
}
var m = map[string]interface{}{"name": "Alice", "age": 30}
var p Person
mapstructure.Decode(m, &p)
structs:
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 30}
m := structs.Map(p)
Key Differences
- mapstructure focuses on decoding maps into structs, while structs primarily deals with struct reflection and conversion to maps
- structs provides more utilities for working with struct fields directly
- mapstructure offers more advanced decoding options and customization
Use Cases
- Use mapstructure when dealing with complex data structures or when decoding from various sources (JSON, YAML, etc.)
- Use structs for simpler struct manipulation, reflection, and conversion to maps
Both libraries have their strengths and are suitable for different scenarios. Choose based on your specific requirements and the complexity of your data structures.
:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
Pros of validator
- More comprehensive validation capabilities, including custom validation functions
- Supports both struct and field-level validations
- Offers localization for error messages
Cons of validator
- Steeper learning curve due to more complex API
- Requires additional setup and configuration for advanced features
Code Comparison
structs:
type User struct {
Name string `structs:"name"`
Age int `structs:"age"`
}
user := User{Name: "John", Age: 30}
m := structs.Map(user)
validator:
type User struct {
Name string `validate:"required,min=2,max=50"`
Age int `validate:"required,gte=18,lte=120"`
}
user := User{Name: "John", Age: 30}
err := validate.Struct(user)
Key Differences
- structs focuses on struct manipulation and conversion
- validator specializes in data validation and error handling
- structs has a simpler API for basic struct operations
- validator offers more advanced features for complex validation scenarios
Use Cases
structs:
- Simple struct to map conversions
- Basic struct manipulation tasks
validator:
- Comprehensive input validation
- Complex data validation requirements
- Projects needing localized error messages
Both libraries serve different purposes, with structs being more suitable for straightforward struct operations and validator excelling in robust data validation scenarios.
Copier for golang, copy value from struct to struct and more
Pros of copier
- Supports deep copying of nested structs and slices
- Allows custom field mapping and conversion functions
- Can handle copying between different types with similar field names
Cons of copier
- May have performance overhead for complex structures
- Requires reflection, which can impact compile-time type safety
- Less focused on struct analysis and more on copying/conversion
Code Comparison
copier:
type User struct {
Name string
Age int
}
type Employee struct {
Name string
Age int
Company string
}
user := User{Name: "John", Age: 30}
employee := Employee{}
copier.Copy(&employee, &user)
structs:
type User struct {
Name string
Age int
}
user := User{Name: "John", Age: 30}
fields := structs.Fields(user)
for _, field := range fields {
fmt.Printf("%s: %v\n", field.Name(), field.Value())
}
The copier example demonstrates copying between different struct types, while the structs example shows how to analyze and iterate over struct fields. structs is more focused on struct introspection, while copier emphasizes data copying and conversion between types.
Mergo: merging Go structs and maps since 2013
Pros of mergo
- Supports deep merging of structs and maps
- Allows for custom merge functions
- Handles complex nested structures more effectively
Cons of mergo
- May have slightly higher performance overhead for complex merges
- Less focused on struct field analysis compared to structs
- Requires more setup for custom merge behavior
Code Comparison
mergo:
type Foo struct {
A string
B int
}
a := Foo{A: "one", B: 2}
b := Foo{A: "two"}
mergo.Merge(&a, b)
structs:
type Foo struct {
A string
B int
}
a := Foo{A: "one", B: 2}
m := structs.Map(a)
Summary
mergo focuses on merging complex data structures, offering flexibility for custom merge behaviors. It excels at handling nested structures but may have slightly higher performance overhead for complex operations. structs, on the other hand, specializes in struct field analysis and conversion to maps, providing a more straightforward approach for simpler use cases. The choice between the two depends on the specific requirements of your project, with mergo being more suitable for complex merging operations and structs for simpler struct manipulations and conversions.
safe and easy casting from one type to another in Go
Pros of cast
- More comprehensive type conversion capabilities, handling a wider range of data types
- Provides additional utility functions for string manipulation and formatting
- Actively maintained with regular updates and improvements
Cons of cast
- Larger codebase and dependency footprint compared to structs
- May have a steeper learning curve due to more extensive functionality
Code Comparison
structs:
s := struct{Name string}{"John"}
m := structs.Map(s)
cast:
var i interface{} = "5"
v := cast.ToInt(i)
Summary
structs focuses primarily on struct manipulation and conversion to maps, while cast offers a broader range of type conversion and manipulation functions. structs is more lightweight and specialized, whereas cast provides a more comprehensive toolkit for type conversions and data manipulation in Go. The choice between the two depends on the specific needs of your project and the breadth of functionality required.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Archived project. No maintenance.
This project is not maintained anymore and is archived. Feel free to fork and make your own changes if needed. For more detail read my blog post: Taking an indefinite sabbatical from my projects
Thanks to everyone for their valuable feedback and contributions.
Structs
Structs contains various utilities to work with Go (Golang) structs. It was
initially used by me to convert a struct into a map[string]interface{}
. With
time I've added other utilities for structs. It's basically a high level
package based on primitives from the reflect package. Feel free to add new
functions or improve the existing code.
Install
go get github.com/fatih/structs
Usage and Examples
Just like the standard lib strings
, bytes
and co packages, structs
has
many global functions to manipulate or organize your struct data. Lets define
and declare a struct:
type Server struct {
Name string `json:"name,omitempty"`
ID int
Enabled bool
users []string // not exported
http.Server // embedded
}
server := &Server{
Name: "gopher",
ID: 123456,
Enabled: true,
}
// Convert a struct to a map[string]interface{}
// => {"Name":"gopher", "ID":123456, "Enabled":true}
m := structs.Map(server)
// Convert the values of a struct to a []interface{}
// => ["gopher", 123456, true]
v := structs.Values(server)
// Convert the names of a struct to a []string
// (see "Names methods" for more info about fields)
n := structs.Names(server)
// Convert the values of a struct to a []*Field
// (see "Field methods" for more info about fields)
f := structs.Fields(server)
// Return the struct name => "Server"
n := structs.Name(server)
// Check if any field of a struct is initialized or not.
h := structs.HasZero(server)
// Check if all fields of a struct is initialized or not.
z := structs.IsZero(server)
// Check if server is a struct or a pointer to struct
i := structs.IsStruct(server)
Struct methods
The structs functions can be also used as independent methods by creating a new
*structs.Struct
. This is handy if you want to have more control over the
structs (such as retrieving a single Field).
// Create a new struct type:
s := structs.New(server)
m := s.Map() // Get a map[string]interface{}
v := s.Values() // Get a []interface{}
f := s.Fields() // Get a []*Field
n := s.Names() // Get a []string
f := s.Field(name) // Get a *Field based on the given field name
f, ok := s.FieldOk(name) // Get a *Field based on the given field name
n := s.Name() // Get the struct name
h := s.HasZero() // Check if any field is uninitialized
z := s.IsZero() // Check if all fields are uninitialized
Field methods
We can easily examine a single Field for more detail. Below you can see how we get and interact with various field methods:
s := structs.New(server)
// Get the Field struct for the "Name" field
name := s.Field("Name")
// Get the underlying value, value => "gopher"
value := name.Value().(string)
// Set the field's value
name.Set("another gopher")
// Get the field's kind, kind => "string"
name.Kind()
// Check if the field is exported or not
if name.IsExported() {
fmt.Println("Name field is exported")
}
// Check if the value is a zero value, such as "" for string, 0 for int
if !name.IsZero() {
fmt.Println("Name is initialized")
}
// Check if the field is an anonymous (embedded) field
if !name.IsEmbedded() {
fmt.Println("Name is not an embedded field")
}
// Get the Field's tag value for tag name "json", tag value => "name,omitempty"
tagValue := name.Tag("json")
Nested structs are supported too:
addrField := s.Field("Server").Field("Addr")
// Get the value for addr
a := addrField.Value().(string)
// Or get all fields
httpServer := s.Field("Server").Fields()
We can also get a slice of Fields from the Struct type to iterate over all fields. This is handy if you wish to examine all fields:
s := structs.New(server)
for _, f := range s.Fields() {
fmt.Printf("field name: %+v\n", f.Name())
if f.IsExported() {
fmt.Printf("value : %+v\n", f.Value())
fmt.Printf("is zero : %+v\n", f.IsZero())
}
}
Credits
License
The MIT License (MIT) - see LICENSE.md for more details
Top Related Projects
Go library for decoding generic map values into native Go structures and vice versa.
:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
Copier for golang, copy value from struct to struct and more
Mergo: merging Go structs and maps since 2013
safe and easy casting from one type to another in Go
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot