Skip to content

Latest commit

 

History

History
255 lines (204 loc) · 6.19 KB

File metadata and controls

255 lines (204 loc) · 6.19 KB

Reflections Library

The reflections library provides a set of utilities for working with Go's reflection capabilities. It simplifies common reflection tasks such as getting and setting struct fields, inspecting field types and tags, and working with nested structs.

Installation

To use this package, import it in your Go code:

import "github.com/getevo/evo/v2/lib/reflections"

Features

  • Field Access: Get and set struct fields by name
  • Field Inspection: Get field kind, type, and tag information
  • Field Discovery: List all fields in a struct
  • Tag Handling: Access and search for struct tags
  • Deep Reflection: Work with nested struct fields
  • Type Safety: Proper error handling for type mismatches

Functions


GetField

func GetField(obj interface{}, name string) (interface{}, error)

Description: Returns the value of the provided object field.


GetFieldKind

func GetFieldKind(obj interface{}, name string) (reflect.Kind, error)

Description: Returns the kind of the provided object field.


GetFieldType

func GetFieldType(obj interface{}, name string) (string, error)

Description: Returns the type of the provided object field.


GetFieldTag

func GetFieldTag(obj interface{}, fieldName, tagKey string) (string, error)

Description: Returns the tag value of the provided object field.


GetFieldNameByTagValue

func GetFieldNameByTagValue(obj interface{}, tagKey, tagValue string) (string, error)

Description: Looks up a field with a matching tag value in the provided object.


SetField

func SetField(obj interface{}, name string, value interface{}) error

Description: Sets the value of the provided object field.


HasField

func HasField(obj interface{}, name string) (bool, error)

Description: Checks if the provided object has a field with the given name.


Fields

func Fields(obj interface{}) ([]string, error)

Description: Returns the names of the fields in the provided object.


FieldsDeep

func FieldsDeep(obj interface{}) ([]string, error)

Description: Returns the "flattened" names of the fields in the provided object, including fields from anonymous inner structs.


Items

func Items(obj interface{}) (map[string]interface{}, error)

Description: Returns the field:value pairs of the provided object as a map.


ItemsDeep

func ItemsDeep(obj interface{}) (map[string]interface{}, error)

Description: Returns the "flattened" field:value pairs of the provided object as a map, including fields from anonymous inner structs.


Tags

func Tags(obj interface{}, key string) (map[string]string, error)

Description: Returns the tags of the fields in the provided object as a map.


TagsDeep

func TagsDeep(obj interface{}, key string) (map[string]string, error)

Description: Returns the "flattened" tags of the fields in the provided object as a map, including fields from anonymous inner structs.


Usage Examples

Getting and Setting Fields

package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/reflections"
)

type Person struct {
    Name    string
    Age     int
    Address string
}

func main() {
    person := Person{
        Name:    "John Doe",
        Age:     30,
        Address: "123 Main St",
    }
    
    // Get a field value
    name, err := reflections.GetField(person, "Name")
    if err == nil {
        fmt.Printf("Name: %s\n", name)
    }
    
    // Set a field value
    err = reflections.SetField(&person, "Age", 31)
    if err == nil {
        fmt.Printf("Updated age: %d\n", person.Age)
    }
    
    // Check if a field exists
    hasField, _ := reflections.HasField(person, "Email")
    fmt.Printf("Has Email field: %t\n", hasField)
}

Working with Field Types and Tags

package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/reflections"
)

type User struct {
    ID        int    `json:"id" db:"user_id"`
    Username  string `json:"username" db:"username"`
    Email     string `json:"email" db:"email"`
    CreatedAt string `json:"created_at" db:"created_at"`
}

func main() {
    user := User{
        ID:        1,
        Username:  "johndoe",
        Email:     "john@example.com",
        CreatedAt: "2023-01-01",
    }
    
    // Get field kind
    kind, _ := reflections.GetFieldKind(user, "Username")
    fmt.Printf("Username field kind: %s\n", kind)
    
    // Get field type
    fieldType, _ := reflections.GetFieldType(user, "ID")
    fmt.Printf("ID field type: %s\n", fieldType)
    
    // Get field tag
    jsonTag, _ := reflections.GetFieldTag(user, "Email", "json")
    fmt.Printf("Email JSON tag: %s\n", jsonTag)
    
    // Find field by tag value
    fieldName, _ := reflections.GetFieldNameByTagValue(user, "db", "user_id")
    fmt.Printf("Field with db tag 'user_id': %s\n", fieldName)
}

Working with Nested Structs

package main

import (
    "fmt"
    "github.com/getevo/evo/v2/lib/reflections"
)

type Address struct {
    Street  string
    City    string
    Country string
}

type Customer struct {
    Name    string
    Age     int
    Address Address
}

func main() {
    customer := Customer{
        Name: "Jane Doe",
        Age:  28,
        Address: Address{
            Street:  "456 Oak Ave",
            City:    "Metropolis",
            Country: "USA",
        },
    }
    
    // Get all fields including nested ones
    fieldsDeep, _ := reflections.FieldsDeep(customer)
    fmt.Println("All fields (deep):", fieldsDeep)
    
    // Get all field values including nested ones
    itemsDeep, _ := reflections.ItemsDeep(customer)
    for field, value := range itemsDeep {
        fmt.Printf("%s: %v\n", field, value)
    }
}

How It Works

The reflections library uses Go's built-in reflect package to inspect and manipulate struct values at runtime. It provides a higher-level API that makes common reflection tasks easier and safer.

The library handles various edge cases, such as unexported fields, pointer values, and nested structs. It also provides both shallow and deep operations for working with nested structures.