Skip to content

Import path: gitlab.soludian.com/soludian/fountain/libs/base/structs

structs

go
import "gitlab.soludian.com/soludian/fountain/libs/base/structs"

Package structs Provide some extends util functions for struct. eg: tag parse, struct init, value set

Index

Variables

ErrNotAnStruct error var emptyStringMap = make(map_util.SMap)

go
var ErrNotAnStruct = errors.New("must input an struct value")

func ExportPrivate

go
func ExportPrivate(opt *MapOptions)

ExportPrivate merge anonymous struct fields to parent map

func FillJSONFields

go
func FillJSONFields[T any](t T) T

Before save data from Database, need call FillJSONFields to fill all slice fields Description: The FillJSONFields function is designed to automatically populate fields within a struct by converting JSON representations to their corresponding types. This function leverages Go's reflection capabilities to identify and perform the conversion for fields based on field name/tag conventions. To use the FillJSONFields function, you should provide a struct variable or a pointer to a struct. The function will identify fields in the struct that require population based on the field name conventions and perform the population process.

FillJSONFields tự động chuyển các trường chứa chuỗi json thành các trường tương ứng dựa vào tag "marshal_<to/from>:"<FieldName/tag:tagValue/tag=tagValue>" hoặc suffix "JSON" (field json nguồn).

Parameters: t: A variable or a pointer to a struct that contains the fields to be populated with JSON data.

Return: Returns a value of the same type as the input t. If t is a pointer, the function returns a pointer to the populated struct; otherwise, it returns the populated struct directly.

Field Name Conventions: This function relies on field name conventions to determine fields requiring population: Fields to be populated from JSON data must have the "JSON" suffix. Fields that hold the corresponding data in JSON format should have the same name as the JSON field but without the "JSON" suffix.

Usage:

type Person struct {
    Name     string
    NameJSON string
    Age      int
    AgeJ     string `marshal_from:"Age"`
	      Value    int `marshal_to:"json=value_j"`
    ValueJ   string `json:"value_j"`
}
func main() {
    person := &Person{
        NameJSON: `"Name"`,
           AgeJ:     `"12"`,
           ValueJ:     `"21"`,
    }
    populatedPerson := FillJSONFields(person)
    fmt.Println("Name:", populatedPerson.Name)
    fmt.Println("Age:", populatedPerson.Age)
}

func Init

go
func Init(ptr any, optFns ...InitOptFunc) error

Init struct default value by field "default" tag.

func InitDefaults

go
func InitDefaults(ptr any, optFns ...InitOptFunc) error

InitDefaults init struct default value by field "default" tag.

TIPS:

Support init field types: string, bool, intX, uintX, floatX, array, slice

Example:

type User1 struct {
	Name string `default:"inhere"`
	Age  int32  `default:"30"`
}

u1 := &User1{}
err = structs.InitDefaults(u1)
fmt.Printf("%+v\n", u1) // Output: {Name:inhere Age:30}
Example

go
package main

import (
	"fmt"

	"gitlab.soludian.com/soludian/fountain/libs/base/dump"
	"gitlab.soludian.com/soludian/fountain/libs/base/structs"
)

func main() {
	type Extra struct {
		City   string `default:"chengdu"`
		Github string `default:"https://github.com/inhere"`
	}
	type User struct {
		Name  string `default:"inhere"`
		Age   int    `default:"30"`
		Extra Extra  `default:""` // add tag for init sub struct
	}

	u := &User{}
	_ = structs.InitDefaults(u)
	dump.P(u)
	/*dump:
	&structs_test.User {
	  Name: string("inhere"), #len=6
	  Age: int(30),
	  Extra: structs_test.Extra {
	    City: string("chengdu"), #len=7
	    Github: string("https://github.com/inhere"), #len=25
	  },
	},
	*/

	fmt.Println("Name:", u.Name)
	fmt.Println("Age:", u.Age)
	fmt.Println("Extra.City:", u.Extra.City)
	fmt.Println("Extra.Github:", u.Extra.Github)
}

Output

Name: inhere
Age: 30
Extra.City: chengdu
Extra.Github: https://github.com/inhere

func IsExported

go
func IsExported(name string) bool

IsExported field name on struct

func IsUnexported

go
func IsUnexported(name string) bool

IsUnexported field name on struct

func MarshalData

go
func MarshalData(t any) error

After get data from Database, need call MarshalData to fill all slice fields; MarshalData tự động chuyển đổi các trường không phải kiểu nguyên tố thành JSON tương ứng với field nguồn/đích có tag tag "marshal_<to/from>:"<FieldName/tag:tagValue/tag=tagValue>", suffix "JSON".

Description: The MarshalData function is used to automatically convert fields within a struct between JSON format and string format. This function utilizes the flexibility of reflection in Go to identify fields to be converted based on field name conventions and performs the conversion process.

To use the MarshalData function, you need to pass a pointer to a struct variable. The function will automatically identify fields in the struct that need conversion based on field name conventions and perform the conversion process.

Parameters: t: A variable of type pointer to a struct containing the data to be converted.

Return error: Returns nil if the conversion process is successful. Returns an error if an issue occurs during the conversion process.

Field Name Conventions: This function relies on field name conventions to determine fields requiring conversion: Fields to be converted from JSON to string format must have the "JSON" suffix. Fields to be converted from string to JSON format must have the same name as the corresponding JSON field, but without the "JSON" suffix.

Benchmark 1: BenchmarkUnmarshalJSON/MarshalData-12 135957 8628 ns/op 3124 B/op 124 allocs/op

Usage:

type Person struct {
    Scopes   []string `json:"scopes,omitempty" marshal_to:"ScopesJ"`
    ScopesJ  string `json:"name_j" unmarshal_from:"json:scopes"`
    Age      int `json:"age" marshal_to:"AgeJ"`
    AgeJ     string `json:"age_j" marshal_to:"Age"`
}
func main() {
    person := &Person{
        ScopesJ: `{"first_name": "John", "last_name": "Doe"}`,
        AgeJSON:  `"30"`,
    }
    err := UnmarshalJSON(person)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Name:", person.Scopes)
    fmt.Println("Age:", person.Age)
}

func MergeAnonymous

go
func MergeAnonymous(opt *MapOptions)

MergeAnonymous merge anonymous struct fields to parent map

func MustToMap

go
func MustToMap(st any, optFns ...MapOptFunc) map[string]any

MustToMap alis of TryToMap, but will panic on error

func MustToSMap

go
func MustToSMap(st any, optFns ...MapOptFunc) map[string]string

MustToSMap alias of ToStringMap(), but will panic on error

func ParseReflectTags

go
func ParseReflectTags(rt reflect.Type, tagNames []string) (map[string]map_util.SMap, error)

ParseReflectTags parse struct tags info.

func ParseTagValueDefault

go
func ParseTagValueDefault(field, tagVal string) (mp map_util.SMap, err error)

ParseTagValueDefault parse like json tag value.

see json.Marshal():

// JSON as key "myName", skipped if empty.
Field int `json:"myName,omitempty"`

// Field appears in JSON as key "Field" (the default), but skipped if empty.
Field int `json:",omitempty"`

// Field is ignored by this package.
Field int `json:"-"`

// Field appears in JSON as key "-".
Field int `json:"-,"`

Int64String int64 `json:",string"`

Returns:

{
	"name": "myName", // maybe is empty, on tag value is "-"
	"omitempty": "true",
	"string": "true",
	// ... more custom bool settings.
}

func ParseTagValueNamed

go
func ParseTagValueNamed(field, tagVal string, keys ...string) (mp map_util.SMap, err error)

ParseTagValueNamed parse k-v tag value string. it's like INI format contents.

Examples:

eg: "name=val0;shorts=i;required=true;desc=a message"
=>
{name: val0, shorts: i, required: true, desc: a message}

func ParseTagValueQuick

go
func ParseTagValueQuick(tagVal string, defines []string) map_util.SMap

ParseTagValueQuick quick parse tag value string by sep(;)

func ParseTags

go
func ParseTags(st any, tagNames []string) (map[string]map_util.SMap, error)

ParseTags for parse struct tags.

func SetValues

go
func SetValues(ptr any, data map[string]any, optFns ...SetOptFunc) error

SetValues set values to struct ptr from map data.

TIPS:

Only support set: string, bool, intX, uintX, floatX

func StructName

go
func StructName(v any) string

StructName returns a normalized name of the passed structure.

func StructToMap

go
func StructToMap(st any, optFns ...MapOptFunc) (map[string]any, error)

StructToMap quickly convert structs to map[string]any by reflect. Can custom export field name by tag `json` or custom tag

func ToMap

go
func ToMap(st any, optFns ...MapOptFunc) map[string]any

ToMap quickly convert structs to map by reflect

Example

go
package main

import (
	"fmt"

	"gitlab.soludian.com/soludian/fountain/libs/base/dump"
	"gitlab.soludian.com/soludian/fountain/libs/base/structs"
)

func main() {
	type Extra struct {
		City   string `json:"city"`
		Github string `json:"github"`
	}
	type User struct {
		Name  string `json:"name"`
		Age   int    `json:"age"`
		Extra Extra  `json:"extra"`
	}

	u := &User{
		Name: "inhere",
		Age:  30,
		Extra: Extra{
			City:   "chengdu",
			Github: "https://github.com/inhere",
		},
	}

	mp := structs.ToMap(u)
	dump.P(mp)
	/*dump:
	map[string]interface {} { #len=3
	  "name": string("inhere"), #len=6
	  "age": int(30),
	  "extra": map[string]interface {} { #len=2
	    "city": string("chengdu"), #len=7
	    "github": string("https://github.com/inhere"), #len=25
	  },
	},
	*/

	fmt.Println("mp.ame:", mp["name"])
	fmt.Println("mp.age:", mp["age"])
}

Output

mp.ame: inhere
mp.age: 30

func ToSMap

go
func ToSMap(st any, optFns ...MapOptFunc) map[string]string

ToSMap quickly and safe convert structs to map[string]string by reflect

func ToString

go
func ToString(st any, optFns ...MapOptFunc) string

ToString quickly format struct to string

func TryToMap

go
func TryToMap(st any, optFns ...MapOptFunc) (map[string]any, error)

TryToMap simple convert structs to map by reflect

func TryToSMap

go
func TryToSMap(st any, optFns ...MapOptFunc) (map[string]string, error)

TryToSMap quickly convert structs to map[string]string by reflect

func WithParseDefault

go
func WithParseDefault(opt *SetOptions)

WithParseDefault value by tag "default"

type Aliases

Aliases implemented a simple string alias map.

go
type Aliases struct {

    // Checker custom add alias name checker func
    Checker func(alias string) // should return bool OR error ??
    // contains filtered or unexported fields
}

func NewAliases

go
func NewAliases(checker func(alias string)) *Aliases

NewAliases create

func (*Aliases) AddAlias

go
func (as *Aliases) AddAlias(real, alias string)

AddAlias to the Aliases

func (*Aliases) AddAliasMap

go
func (as *Aliases) AddAliasMap(alias2real map[string]string)

AddAliasMap to the Aliases

func (*Aliases) AddAliases

go
func (as *Aliases) AddAliases(real string, aliases []string)

AddAliases to the Aliases

func (*Aliases) HasAlias

go
func (as *Aliases) HasAlias(alias string) bool

HasAlias in the Aliases

func (*Aliases) Mapping

go
func (as *Aliases) Mapping() map[string]string

Mapping get all aliases mapping

func (*Aliases) ResolveAlias

go
func (as *Aliases) ResolveAlias(alias string) string

ResolveAlias by given name.

type Data

Data struct, allow enable lock

go
type Data struct {
    sync.RWMutex
    // contains filtered or unexported fields
}

func NewData

go
func NewData() *Data

NewData create new data instance

func NewLiteData

go
func NewLiteData(data map[string]any) *Data

NewLiteData create, not locked

func (*Data) BoolVal

go
func (d *Data) BoolVal(key string) bool

BoolVal get from data

func (*Data) Data

go
func (d *Data) Data() map[string]any

Data get all

func (*Data) DataLen

go
func (d *Data) DataLen() int

DataLen of data

func (*Data) EnableLock

go
func (d *Data) EnableLock() *Data

EnableLock for operate data

func (*Data) Get

go
func (d *Data) Get(key string) any

Get val from data

func (*Data) GetVal

go
func (d *Data) GetVal(key string) any

GetVal get from data

func (*Data) IntVal

go
func (d *Data) IntVal(key string) int

IntVal get from data

func (*Data) Merge

go
func (d *Data) Merge(mp map[string]any)

Merge load new data

func (*Data) ResetData

go
func (d *Data) ResetData()

ResetData all data

func (*Data) Set

go
func (d *Data) Set(key string, val any)

Set value to data

func (*Data) SetData

go
func (d *Data) SetData(data map[string]any)

SetData set all data

func (*Data) SetValue

go
func (d *Data) SetValue(key string, val any)

SetValue to data

func (*Data) StrVal

go
func (d *Data) StrVal(key string) string

StrVal get from data

func (*Data) String

go
func (d *Data) String() string

String format data

func (*Data) Value

go
func (d *Data) Value(key string) (val any, ok bool)

Value get from data

func (*Data) WithLock

go
func (d *Data) WithLock() *Data

WithLock for operate data

type InitOptFunc

InitOptFunc define

go
type InitOptFunc func(opt *InitOptions)

type InitOptions

InitOptions struct

go
type InitOptions struct {
    // TagName default value tag name. tag: default
    TagName string
    // ParseEnv var name on default value. eg: `default:"${APP_ENV}"`
    //
    // default: false
    ParseEnv bool
    // ValueHook before set value hook TODO
    ValueHook func(val string) any
}

type LiteData

LiteData simple map[string]any struct. no lock

go
type LiteData = Data

type MapOptFunc

MapOptFunc define

go
type MapOptFunc func(opt *MapOptions)

func WithMapTagName

go
func WithMapTagName(tagName string) MapOptFunc

WithMapTagName set tag name for map field

type MapOptions

MapOptions for convert struct to map

go
type MapOptions struct {
    // TagName for map filed. default is "json"
    TagName string
    // ParseDepth for parse. TODO support depth
    ParseDepth int
    // MergeAnonymous struct fields to parent map. default is true
    MergeAnonymous bool
    // ExportPrivate export private fields. default is false
    ExportPrivate bool
}

type OrderedData

OrderedData data TODO

go
type OrderedData struct {
    map_util.Data
    // contains filtered or unexported fields
}

func NewOrderedData

go
func NewOrderedData(cap int) *OrderedData

NewOrderedData instance.

func (*OrderedData) Load

go
func (om *OrderedData) Load(data map[string]any)

Load data

func (*OrderedData) Set

go
func (om *OrderedData) Set(key string, val any)

Set key and value to map

type SMap

SMap simple map[string]string struct.

go
type SMap struct {
    // contains filtered or unexported fields
}

type SetOptFunc

SetOptFunc define

go
type SetOptFunc func(opt *SetOptions)

type SetOptions

SetOptions for set values to struct

go
type SetOptions struct {
    // FieldTagName get field name for read value. default tag: json
    FieldTagName string
    // ValueHook before set value hook TODO
    ValueHook func(val any) any

    // ParseDefault init default value by DefaultValTag tag value.
    // default: false
    //
    // see InitDefaults()
    ParseDefault bool

    // DefaultValTag name. tag: default
    DefaultValTag string

    // ParseDefaultEnv parse env var on default tag. eg: `default:"${APP_ENV}"`
    //
    // default: false
    ParseDefaultEnv bool
}

type TagParser

TagParser struct

go
type TagParser struct {
    // TagNames want parsed tag names.
    TagNames []string
    // ValueFunc tag value parse func.
    ValueFunc TagValFunc
    // contains filtered or unexported fields
}

func NewTagParser

go
func NewTagParser(tagNames ...string) *TagParser

NewTagParser instance

func (*TagParser) Info

go
func (p *TagParser) Info(field, tag string) (map_util.SMap, error)

Info parse the give field, returns tag value info.

info, err := p.Info("Name", "json")
exportField := info.Get("name")

func (*TagParser) Parse

go
func (p *TagParser) Parse(st any) error

Parse an struct value

Example

go
package main

import (
	"fmt"

	"gitlab.soludian.com/soludian/fountain/libs/base/dump"
	"gitlab.soludian.com/soludian/fountain/libs/base/fn"
	"gitlab.soludian.com/soludian/fountain/libs/base/structs"
)

func main() {
	type User struct {
		Age   int    `json:"age" yaml:"age" default:"23"`
		Name  string `json:"name,omitempty" yaml:"name" default:"inhere"`
		inner string //lint:ignore U1000 for test
	}

	u := &User{}
	p := structs.NewTagParser("json", "yaml", "default")
	fn.MustOK(p.Parse(u))

	tags := p.Tags()
	dump.P(tags)
	/*tags:
	map[string]map_util.SMap { #len=2
	  "Age": map_util.SMap { #len=3
	    "json": string("age"), #len=3
	    "yaml": string("age"), #len=3
	    "default": string("23"), #len=2
	  },
	  "Name": map_util.SMap { #len=3
	    "default": string("inhere"), #len=6
	    "json": string("name,omitempty"), #len=14
	    "yaml": string("name"), #len=4
	  },
	},
	*/

	dump.P(p.Info("name", "json"))
	/*info:
	map_util.SMap { #len=2
	  "name": string("name"), #len=4
	  "omitempty": string("true"), #len=4
	},
	*/

	fmt.Println(
		tags["Age"].Get("json"),
		tags["Age"].Get("default"),
	)

}

Output

age 23

Example (Parse Tag Value Define)

go
package main

import (
	"fmt"

	"gitlab.soludian.com/soludian/fountain/libs/base/dump"
	"gitlab.soludian.com/soludian/fountain/libs/base/fn"
	"gitlab.soludian.com/soludian/fountain/libs/base/structs"
)

func main() {
	// eg: "desc;required;default;shorts"
	type MyCmd struct {
		Name string `flag:"set your name;false;INHERE;n"`
	}

	c := &MyCmd{}
	p := structs.NewTagParser("flag")

	sepStr := ";"
	defines := []string{"desc", "required", "default", "shorts"}
	p.ValueFunc = structs.ParseTagValueDefine(sepStr, defines)

	fn.MustOK(p.Parse(c))
	// dump.P(p.Tags())
	/*
		map[string]map_util.SMap { #len=1
		  "Name": map_util.SMap { #len=1
		    "flag": string("set your name;false;INHERE;n"), #len=28
		  },
		},
	*/
	fmt.Println("tags:", p.Tags())

	info, _ := p.Info("Name", "flag")
	dump.P(info)
	/*
		map_util.SMap { #len=4
		  "desc": string("set your name"), #len=13
		  "required": string("false"), #len=5
		  "default": string("INHERE"), #len=6
		  "shorts": string("n"), #len=1
		},
	*/

}

Output

tags: map[Name:{flag:set your name;false;INHERE;n}]

func (*TagParser) ParseType

go
func (p *TagParser) ParseType(rt reflect.Type) error

ParseType parse a struct type value

func (*TagParser) Tags

go
func (p *TagParser) Tags() map[string]map_util.SMap

Tags map data for struct fields

type TagValFunc

TagValFunc handle func

go
type TagValFunc func(field, tagVal string) (map_util.SMap, error)

func ParseTagValueDefine

go
func ParseTagValueDefine(sep string, defines []string) TagValFunc

ParseTagValueDefine parse tag value string by given defines.

Examples:

eg: "desc;required;default;shorts"
type MyStruct {
	Age int `flag:"int option message;;a,b"`
}
sepStr := ";"
defines := []string{"desc", "required", "default", "shorts"}

type Value

Value data store

go
type Value struct {
    // V value
    V any
}

func GetFieldValueByTag

go
func GetFieldValueByTag(st any, tag, tagValue string) (*Value, error)

GetFieldValueByTag get value of st by tag:"tagValue"

Usage:

type User struct {
	 Age int `json:"age"`
 }
 user := &User{Age: 23}
 data, err := structs.GetFieldValueByTag(user, "json", "age")
 if err != nil {
 	// error handler
 }
 fmt.Printf(data) // 23

func NewValue

go
func NewValue(val any) *Value

NewValue instance.

func (*Value) Bool

go
func (v *Value) Bool() bool

Bool value

func (*Value) Float64

go
func (v *Value) Float64() float64

Float64 value

func (*Value) Int

go
func (v *Value) Int() int

Int value get

func (*Value) Int64

go
func (v *Value) Int64() int64

Int64 value

func (*Value) IsEmpty

go
func (v *Value) IsEmpty() bool

IsEmpty value

func (*Value) Reset

go
func (v *Value) Reset()

Reset value

func (*Value) Set

go
func (v *Value) Set(val any)

Set value

func (*Value) SplitToInts

go
func (v *Value) SplitToInts(sep ...string) (ss []int)

SplitToInts split string value to []int. sep default is comma(,)

func (*Value) SplitToStrings

go
func (v *Value) SplitToStrings(sep ...string) (ss []string)

SplitToStrings split string value to strings. sep default is comma(,)

func (*Value) String

go
func (v *Value) String() string

String value

func (*Value) Strings

go
func (v *Value) Strings() (ss []string)

Strings value

func (*Value) Val

go
func (v *Value) Val() any

Val get

type Wrapper

Wrapper struct for read or set field value

go
type Wrapper struct {

    // FieldTagName field name for read/write value. default tag: json
    FieldTagName string
    // contains filtered or unexported fields
}

func NewWrapper

go
func NewWrapper(src any) *Wrapper

NewWrapper create a struct wrapper

func NewWriter

go
func NewWriter(ptr any) *Wrapper

NewWriter create a struct writer

func Wrap

go
func Wrap(src any) *Wrapper

Wrap create a struct wrapper

func WrapValue

go
func WrapValue(rv reflect.Value) *Wrapper

WrapValue create a struct wrapper

func (*Wrapper) Get

go
func (r *Wrapper) Get(name string) any

Get field value by name, name allow use dot syntax.

func (*Wrapper) Lookup

go
func (r *Wrapper) Lookup(name string) (val any, ok bool)

Lookup field value by name, name allow use dot syntax.

func (*Wrapper) Set

go
func (r *Wrapper) Set(name string, val any) error

Set field value by name, name allow use dot syntax.

Generated by gomarkdoc