https://github.com/insei/fmap
FMap is a simple library for working with structs as storage of fields. Switch case and reflect based.
https://github.com/insei/fmap
go golang map-fields reflect reflection struct-as-map
Last synced: 12 months ago
JSON representation
FMap is a simple library for working with structs as storage of fields. Switch case and reflect based.
- Host: GitHub
- URL: https://github.com/insei/fmap
- Owner: Insei
- License: apache-2.0
- Created: 2024-05-21T12:17:28.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-11T08:36:35.000Z (over 1 year ago)
- Last Synced: 2025-03-30T16:46:41.557Z (about 1 year ago)
- Topics: go, golang, map-fields, reflect, reflection, struct-as-map
- Language: Go
- Homepage:
- Size: 43 KB
- Stars: 3
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: Readme.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://codecov.io/github/Insei/fmap)
[](https://github.com/Insei/fmap/actions/workflows/go.yml)
[](https://goreportcard.com/report/github.com/insei/fmap)
[](https://godoc.org/github.com/insei/fmap)
# FMap
FMap is a simple library for working with structs as a storage of fields. Switch case and reflect based.
This is unsafe library, be careful while use.
# Installation
Install via go get. Note that Go 1.18 or newer is required.
```sh
go get github.com/insei/fmap/v3@latest
```
# Description
`fmap.GetFrom(obj any)` and `fmap.Get[T any]()` creates new fmap.Storage. This storage manage access to fmap.Field by field path like in struct.
```go
type Storage interface {
// Find returns the Field object and a boolean value indicating if the field with the given path was found.
// The path parameter represents the path of the field in the struct.
// If the field is found, the method returns the Field object and true.
// If the field is not found, the method returns a nil Field object and false.
Find(path string) (Field, bool)
// MustFind returns the Field object for the field with the given path in the struct.
// If the Field is not found, MustFind panics.
MustFind(path string) Field
// GetAllPaths returns a slice containing all paths of fields in the struct.
GetAllPaths() []string
}
```
fmap.Field is an advanced abstraction level for reflect.StructField with some advanced methods:
```go
type Field interface {
// GetName returns the name of the field.
GetName() string
// GetPkgPath returns the package import path of the Field struct type.
GetPkgPath() string
// GetType returns the reflect.Type of the field.
GetType() reflect.Type
// GetTag returns the reflect.StructTag of the field. The reflect.StructTag is a string.
GetTag() reflect.StructTag
// GetOffset returns the offset of the field in memory relative to the start of the struct.
GetOffset() uintptr
// GetIndex returns the index of the field within its containing struct as a slice of integers.
GetIndex() []int
// GetAnonymous returns a boolean value indicating whether the field is anonymous.
GetAnonymous() bool
// IsExported checks if a field is exported by checking its PkgPath property.
IsExported() bool
// Extended Methods
// Get returns the value of the storage in the provided object.
// It takes a parameter `obj` of type `interface{}`, representing the object.
// It returns the value of the storage as an `interface{}`.
Get(obj any) any
// GetPtr returns the pointer to the field's value in the provided object.
// It takes a parameter `obj` of type `any`, representing the pointer to object.
// It returns the pointer to the field's value as an `any`.
GetPtr(obj any) any
// Set updates the value of the storage in the provided object with the provided value.
// It takes two parameters:
// - obj: interface{}, representing the object pointer containing the field.
// - val: interface{}, representing the new value for the field.
Set(obj any, val any)
// GetStructPath returns the struct path of the field.
// It returns the struct path as a string.
GetStructPath() string
// GetTagPath returns the path of the field's tag value with the given tag name.
// It takes two parameters:
// - tag: string, representing the tag name.
// - ignoreParentTagMissing: bool, representing whether to ignore the missing parent tags or not.
// It returns the tag value path as a string.
GetTagPath(tag string, ignoreParentTagMissing bool) string
// GetParent returns the parent field of the current field, if not exist return nil.
GetParent() Field
// GetDereferencedType returns the dereferenced type of the field.
// It returns the dereferenced type as a reflect.Type.
GetDereferencedType() reflect.Type
// GetDereferenced - uses reflect package for casting field value from obj to direct field value, i.e. dereferenced value.
GetDereferenced(obj any) (any, bool)
}
```
# Example
```go
package main
import (
"time"
"fmt"
"github.com/insei/fmap/v3"
)
type City struct {
Name string `json:"name"`
}
type People struct {
Name string
Age uint8
Birthday time.Time
City City `json:"city"`
}
func main() {
p := &People{}
fields := fmap.Get[People]() // or fmap.GetFrom(p)
fields.MustFind("Name").Set(p, "Test")
fields.MustFind("Age").Set(p, uint8(5))
fields.MustFind("Birthday").Set(p, time.Now())
fields.MustFind("City.Name").Set(p, "DefaultCity")
jsonPath := fields.MustFind("City.Name").GetTagPath("json", false) // city.name
cityField := fields.MustFind("City.Name").GetParent()
cityStruct := cityField.Get(p)
fmt.Print(*p, jsonPath, cityStruct)
}
```
More examples in `field_test.go`, like slice fields, nested structs, pointers etc.
# Benchmarks
`fmap.GetFrom(obj any) map[string]Field`
```
BenchmarkGetFrom
BenchmarkGetFrom-16 93002347 12.62 ns/op 0 B/op 0 allocs/op
```
`Field.Get(obj any) any`
```
BenchmarkFieldGet
BenchmarkFieldGet-16 88818492 14.05 ns/op 0 B/op 0 allocs/op
```
`Raw access to field from struct :)`
```
BenchmarkRawFieldGet
BenchmarkRawFieldGet-16 1000000000 0.2350 ns/op 0 B/op 0 allocs/op
```