Convert Figma logo to code with AI

fatih logostructs

Utilities for Go structs

3,893
694
3,893
0

Top Related Projects

Go library for decoding generic map values into native Go structures and vice versa.

16,499

:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving

5,435

Copier for golang, copy value from struct to struct and more

2,850

Mergo: merging Go structs and maps since 2013

3,497

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

  1. 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]
  1. 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}
  1. 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:

  1. Install the package:

    go get github.com/fatih/structs
    
  2. Import the package in your Go code:

    import "github.com/fatih/structs"
    
  3. 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.

16,499

: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.

5,435

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.

2,850

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.

3,497

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 Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

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 GoDoc Build Status Coverage Status

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