structs

package
v0.5.12 Latest Latest
Warning

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

Go to latest
Published: Sep 14, 2022 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
},

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 interface{}, optFns ...InitOptFunc) error

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

TIPS:

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

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

func MustToMap(st interface{}, optFns ...MapOptFunc) map[string]interface{}

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) (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 interface{}, tagNames []string) (map[string]maputil.SMap, error)

ParseTags for parse struct tags.

func SetValues added in v0.5.11

func SetValues(ptr interface{}, data map[string]interface{}, 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 interface{}, optFns ...MapOptFunc) (map[string]interface{}, error)

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

func ToMap added in v0.4.2

func ToMap(st interface{}, optFns ...MapOptFunc) map[string]interface{}

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

func TryToMap(st interface{}, optFns ...MapOptFunc) (map[string]interface{}, 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]interface{}

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) interface{}

Get val from data

func (*Data) GetVal added in v0.5.12

func (d *Data) GetVal(key string) interface{}

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 interface{})

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 interface{})

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 interface{}, 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) interface{}
}

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) interface{}

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) interface{}

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 interface{}) interface{}

	// 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 interface{}) 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 My
sepStr := ";"
defines := []string{"desc", "required", "default", "shorts"}

type Value added in v0.5.5

type Value struct {
	// V value
	V interface{}
}

Value data store

func NewValue added in v0.5.5

func NewValue(val interface{}) *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 interface{})

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() interface{}

Val get

Jump to

Keyboard shortcuts

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