structs

package
v0.6.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2023 License: MIT Imports: 12 Imported by: 15

README

Structs

Provide some extends util functions for struct. eg: convert, tag parse, struct data init

  • structs.Aliases - implemented a simple string alias map.
  • Convert a struct to map[string]any data
  • Quickly init struct default values by field "default" tag.
  • Quickly set struct field values by map data
  • Parse a struct and collect tags, and parse tag value
  • And more util functions ...

Install

go get github.com/gookit/goutil/structs

Go docs

Usage

Convert to map

structs.ToMap() can be quickly convert a struct value to map[string]any

Examples:

	type User1 struct {
		Name string `json:"name"`
		Age  int    `json:"age"`
		city string
	}

	u1 := &User1{
		Name: "inhere",
		Age:  34,
		city: "somewhere",
	}

	mp := structs.ToMap(u1)
	dump.P(mp)

Output:

map[string]interface {} { #len=2
  "age": int(34),
  "name": string("inhere"), #len=6
},
Init default values

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

Examples:

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
}

u := &User{}
_ = structs.InitDefaults(u, &structs.InitOptions{})
dump.P(u)

Output:

&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
  },
},
Set values from map
data := map[string]interface{}{
    "name": "inhere",
    "age":  234,
    "tags": []string{"php", "go"},
    "city": "chengdu",
}

type User struct {
    Name string   `json:"name"`
    Age  int      `json:"age"`
    Tags []string `json:"tags"`
    City string   `json:"city"`
}

u := &User{}
err := structs.SetValues(u, data)
dump.P(u)

Output:

&structs_test.User {
  Name: string("inhere"), #len=6
  Age: int(234),
  Tags: []string [ #len=2
    string("php"), #len=3
    string("go"), #len=2
  ],
  City: string("chengdu"), #len=7
},
Tags collect and parse

Parse a struct for collect tags, and parse tag value

Examples:

// 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)

goutil.MustOK(p.Parse(c))
dump.P(p.Tags())

Output:

map[string]maputil.SMap { #len=1
  "Name": maputil.SMap { #len=1
    "flag": string("set your name;false;INHERE;n"), #len=28
  },
},

Parse tag value

info, _ := p.Info("Name", "flag")
dump.P(info)

Output:

maputil.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
},

Functions API

func InitDefaults(ptr any, optFns ...InitOptFunc) error
func MustToMap(st any, optFns ...MapOptFunc) map[string]interface{}
func ParseReflectTags(rt reflect.Type, tagNames []string) (map[string]maputil.SMap, error)
func ParseTagValueDefault(field, tagVal string) (mp maputil.SMap, err error)
func ParseTagValueNamed(field, tagVal string, keys ...string) (mp maputil.SMap, err error)
func ParseTags(st any, tagNames []string) (map[string]maputil.SMap, error)
func SetValues(ptr any, data map[string]any, optFns ...SetOptFunc) error
func StructToMap(st any, optFns ...MapOptFunc) (map[string]interface{}, error)
func ToMap(st any, optFns ...MapOptFunc) map[string]interface{}
func TryToMap(st any, optFns ...MapOptFunc) (map[string]interface{}, error)
type Aliases struct{ ... }
    func NewAliases(checker func(alias string)) *Aliases
type Data struct{ ... }
    func NewData() *Data
type InitOptFunc func(opt *InitOptions)
type InitOptions struct{ ... }
type LiteData struct{ ... }
type MapOptFunc func(opt *MapOptions)
type MapOptions struct{ ... }
type SMap struct{ ... }
type SetOptFunc func(opt *SetOptions)
type SetOptions struct{ ... }
type TagParser struct{ ... }
    func NewTagParser(tagNames ...string) *TagParser
type TagValFunc func(field, tagVal string) (maputil.SMap, error)
    func ParseTagValueDefine(sep string, defines []string) TagValFunc
type Value struct{ ... }
    func NewValue(val any) *Value

Testings

go test -v ./structs/...

Test limit by regexp:

go test -v -run ^TestSetByKeys ./structs/...

Documentation

Overview

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

Index

Examples

Constants

This section is empty.

Variables

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

ErrNotAnStruct error var emptyStringMap = make(maputil.SMap)

Functions

func InitDefaults added in v0.5.10

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
package main

import (
	"fmt"

	"github.com/gookit/goutil/dump"
	"github.com/gookit/goutil/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
	}

	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 added in v0.6.1

func IsExported(fieldName string) bool

IsExported field name on struct

func IsUnexported added in v0.6.1

func IsUnexported(fieldName string) bool

IsUnexported field name on struct

func MustToMap added in v0.4.2

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

MustToMap alis of TryToMap, but will panic on error

func ParseReflectTags added in v0.3.10

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

ParseReflectTags parse struct tags info.

func ParseTagValueDefault added in v0.5.10

func ParseTagValueDefault(field, tagVal string) (mp maputil.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 added in v0.5.10

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

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

eg: "name=int0;shorts=i;required=true;desc=int option message"

func ParseTags added in v0.3.10

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

ParseTags for parse struct tags.

func SetValues added in v0.5.11

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

SetValues set data values to struct ptr

TIPS:

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

func StructToMap added in v0.5.10

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 added in v0.4.2

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

ToMap quickly convert structs to map by reflect

Example
package main

import (
	"fmt"

	"github.com/gookit/goutil/dump"
	"github.com/gookit/goutil/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 ToString added in v0.6.2

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

ToString format

func TryToMap added in v0.4.2

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

TryToMap simple convert structs to map by reflect

Types

type Aliases

type Aliases struct {

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

Aliases implemented a simple string alias map.

func NewAliases

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

NewAliases create

func (*Aliases) AddAlias

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

AddAlias to the Aliases

func (*Aliases) AddAliasMap

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

AddAliasMap to the Aliases

func (*Aliases) AddAliases

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

AddAliases to the Aliases

func (*Aliases) HasAlias

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

HasAlias in the Aliases

func (*Aliases) Mapping

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

Mapping get all aliases mapping

func (*Aliases) ResolveAlias

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

ResolveAlias by given name.

type Data added in v0.5.12

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

Data struct, allow enable lock TODO

func NewData added in v0.5.12

func NewData() *Data

NewData create

func (*Data) BoolVal added in v0.5.12

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

BoolVal get from data

func (*Data) Data added in v0.5.12

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

Data get all

func (*Data) DataLen added in v0.5.12

func (d *Data) DataLen() int

DataLen of data

func (*Data) EnableLock added in v0.5.12

func (d *Data) EnableLock() *Data

EnableLock for operate data

func (*Data) Get added in v0.5.12

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

Get val from data

func (*Data) GetVal added in v0.5.12

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

GetVal get from data

func (*Data) IntVal added in v0.5.12

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

IntVal get from data

func (*Data) ResetData added in v0.5.12

func (d *Data) ResetData()

ResetData all data

func (*Data) Set added in v0.5.12

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

Set value to data

func (*Data) SetData added in v0.5.12

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

SetData set all data

func (*Data) SetValue added in v0.5.12

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

SetValue to data

func (*Data) StrVal added in v0.5.12

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

StrVal get from data

func (*Data) String added in v0.5.12

func (d *Data) String() string

String format data

func (*Data) Value added in v0.5.12

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

Value get from data

type InitOptFunc added in v0.5.10

type InitOptFunc func(opt *InitOptions)

InitOptFunc define

type InitOptions added in v0.5.10

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
}

InitOptions struct

type LiteData added in v0.5.12

type LiteData struct {
	// contains filtered or unexported fields
}

LiteData simple map[string]any struct. no lock

func (*LiteData) Data added in v0.5.12

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

Data get all

func (*LiteData) GetVal added in v0.5.12

func (d *LiteData) GetVal(key string) any

GetVal get from data

func (*LiteData) IntVal added in v0.5.12

func (d *LiteData) IntVal(key string) int

IntVal get from data

func (*LiteData) ResetData added in v0.5.12

func (d *LiteData) ResetData()

ResetData all data

func (*LiteData) SetData added in v0.5.12

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

SetData set all data

func (*LiteData) SetValue added in v0.5.12

func (d *LiteData) SetValue(key string, val any)

SetValue to data

func (*LiteData) StrValue added in v0.5.12

func (d *LiteData) StrValue(key string) string

StrValue get from data

func (*LiteData) Value added in v0.5.12

func (d *LiteData) Value(key string) any

Value get from data

type MapOptFunc added in v0.5.10

type MapOptFunc func(opt *MapOptions)

MapOptFunc define

type MapOptions added in v0.5.10

type MapOptions struct {
	TagName string
}

MapOptions struct

type SMap added in v0.5.12

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

SMap simple map[string]string struct.

type SetOptFunc added in v0.5.11

type SetOptFunc func(opt *SetOptions)

SetOptFunc define

type SetOptions added in v0.5.11

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
}

SetOptions for set values to struct

type TagParser added in v0.3.10

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

TagParser struct

func NewTagParser added in v0.5.10

func NewTagParser(tagNames ...string) *TagParser

NewTagParser instance

func (*TagParser) Info added in v0.5.10

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

Info parse the give field, returns tag value info.

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

func (*TagParser) Parse added in v0.5.10

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

Parse an struct value

Example
package main

import (
	"fmt"

	"github.com/gookit/goutil"
	"github.com/gookit/goutil/dump"
	"github.com/gookit/goutil/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
	}

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

	tags := p.Tags()
	dump.P(tags)
	/*tags:
	map[string]maputil.SMap { #len=2
	  "Age": maputil.SMap { #len=3
	    "json": string("age"), #len=3
	    "yaml": string("age"), #len=3
	    "default": string("23"), #len=2
	  },
	  "Name": maputil.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:
	maputil.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 (ParseTagValueDefine)
package main

import (
	"fmt"

	"github.com/gookit/goutil"
	"github.com/gookit/goutil/dump"
	"github.com/gookit/goutil/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)

	goutil.MustOK(p.Parse(c))
	// dump.P(p.Tags())
	/*
		map[string]maputil.SMap { #len=1
		  "Name": maputil.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)
	/*
		maputil.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 added in v0.5.10

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

ParseType parse a struct type value

func (*TagParser) Tags added in v0.5.10

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

Tags map data for struct fields

type TagValFunc added in v0.5.10

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

TagValFunc handle func

func ParseTagValueDefine added in v0.5.10

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 added in v0.5.5

type Value struct {
	// V value
	V any
}

Value data store

func NewValue added in v0.5.5

func NewValue(val any) *Value

NewValue instance.

func (*Value) Bool added in v0.5.5

func (v *Value) Bool() bool

Bool value

func (*Value) Float64 added in v0.5.5

func (v *Value) Float64() float64

Float64 value

func (*Value) Int added in v0.5.5

func (v *Value) Int() int

Int value get

func (*Value) Int64 added in v0.5.5

func (v *Value) Int64() int64

Int64 value

func (*Value) IsEmpty added in v0.5.5

func (v *Value) IsEmpty() bool

IsEmpty value

func (*Value) Reset added in v0.5.5

func (v *Value) Reset()

Reset value

func (*Value) Set added in v0.5.5

func (v *Value) Set(val any)

Set value

func (*Value) SplitToInts added in v0.5.6

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

SplitToInts split string value to []int

func (*Value) SplitToStrings added in v0.5.6

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

SplitToStrings split string value to strings

func (*Value) String added in v0.5.5

func (v *Value) String() string

String value

func (*Value) Strings added in v0.5.5

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

Strings value

func (*Value) Val added in v0.5.5

func (v *Value) Val() any

Val get

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL