diff --git a/goinfo/README.md b/goinfo/README.md new file mode 100644 index 000000000..2df63a6e0 --- /dev/null +++ b/goinfo/README.md @@ -0,0 +1,34 @@ +# GoInfo + + `goutil/goinfo` provide some useful info for golang. + +> Github: https://github.com/gookit/goutil + +## Install + +```bash +go get github.com/gookit/goutil/goinfo +``` + +## Go docs + +- [Go docs](https://pkg.go.dev/github.com/gookit/goutil) + +## Usage + +```go +gover := goinfo.GoVersion() // eg: "1.15.6" + +``` + +## Testings + +```shell +go test -v ./goinfo/... +``` + +Test limit by regexp: + +```shell +go test -v -run ^TestSetByKeys ./goinfo/... +``` diff --git a/stdutil/gofunc.go b/goinfo/gofunc.go similarity index 82% rename from stdutil/gofunc.go rename to goinfo/gofunc.go index 6a2be9c29..0e92feca4 100644 --- a/stdutil/gofunc.go +++ b/goinfo/gofunc.go @@ -1,4 +1,4 @@ -package stdutil +package goinfo import ( "reflect" @@ -10,7 +10,7 @@ import ( // FullFcName struct. type FullFcName struct { - // FullName eg: github.com/gookit/goutil/stdutil.PanicIf + // FullName eg: github.com/gookit/goutil/goinfo.PanicIf FullName string pkgPath string pkgName string @@ -32,13 +32,13 @@ func (ffn *FullFcName) Parse() { ffn.pkgPath += ffn.pkgName } -// PkgPath string get. eg: github.com/gookit/goutil/stdutil +// PkgPath string get. eg: github.com/gookit/goutil/goinfo func (ffn *FullFcName) PkgPath() string { ffn.Parse() return ffn.pkgPath } -// PkgName string get. eg: stdutil +// PkgName string get. eg: goinfo func (ffn *FullFcName) PkgName() string { ffn.Parse() return ffn.pkgName @@ -59,8 +59,8 @@ func (ffn *FullFcName) String() string { // // eg: // -// // OUTPUT: github.com/gookit/goutil/stdutil.PanicIf -// stdutil.FuncName(stdutil.PkgName) +// // OUTPUT: github.com/gookit/goutil/goinfo.PanicIf +// goinfo.FuncName(goinfo.PkgName) func FuncName(fn any) string { return runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() } @@ -75,12 +75,13 @@ func CutFuncName(fullFcName string) (pkgPath, shortFnName string) { // // Usage: // -// fullFcName := stdutil.FuncName(fn) -// pgkName := stdutil.PkgName(fullFcName) +// fullFcName := goinfo.FuncName(fn) +// pgkName := goinfo.PkgName(fullFcName) func PkgName(fullFcName string) string { for { lastPeriod := strings.LastIndex(fullFcName, ".") lastSlash := strings.LastIndex(fullFcName, "/") + if lastPeriod > lastSlash { fullFcName = fullFcName[:lastPeriod] } else { diff --git a/goinfo/gofunc_test.go b/goinfo/gofunc_test.go new file mode 100644 index 000000000..cf1d215e2 --- /dev/null +++ b/goinfo/gofunc_test.go @@ -0,0 +1,47 @@ +package goinfo_test + +import ( + "testing" + + "github.com/gookit/goutil/dump" + "github.com/gookit/goutil/goinfo" + "github.com/gookit/goutil/testutil/assert" +) + +func TestFuncName(t *testing.T) { + name := goinfo.FuncName(goinfo.PkgName) + assert.Eq(t, "github.com/gookit/goutil/goinfo.PkgName", name) +} + +func TestPkgName(t *testing.T) { + name := goinfo.PkgName(goinfo.FuncName(goinfo.GetCallerInfo)) + assert.Eq(t, "github.com/gookit/goutil/goinfo", name) +} + +func TestFullFcName_Parse(t *testing.T) { + fullName := goinfo.FuncName(goinfo.GetCallerInfo) + + ffn := goinfo.FullFcName{FullName: fullName} + ffn.Parse() + assert.Eq(t, fullName, ffn.String()) + assert.Eq(t, "goinfo", ffn.PkgName()) + assert.Eq(t, "GetCallerInfo", ffn.FuncName()) + assert.Eq(t, "github.com/gookit/goutil/goinfo", ffn.PkgPath()) + dump.P(ffn) + + st := goinfo.FullFcName{} + fullName = goinfo.FuncName(st.FuncName) + + ffn = goinfo.FullFcName{FullName: fullName} + ffn.Parse() + assert.Eq(t, "(*FullFcName).FuncName-fm", ffn.FuncName()) + dump.P(ffn) +} + +func TestCutFuncName(t *testing.T) { + fullName := goinfo.FuncName(goinfo.GetCallerInfo) + + pkgPath, funcName := goinfo.CutFuncName(fullName) + assert.Eq(t, "GetCallerInfo", funcName) + assert.Eq(t, "github.com/gookit/goutil/goinfo", pkgPath) +} diff --git a/goinfo/goinfo.go b/goinfo/goinfo.go new file mode 100644 index 000000000..c615b467a --- /dev/null +++ b/goinfo/goinfo.go @@ -0,0 +1,9 @@ +// Package goinfo provide some standard util functions for go. +package goinfo + +import "runtime" + +// GoVersion get go runtime version. eg: "1.18.2" +func GoVersion() string { + return runtime.Version()[2:] +} diff --git a/goinfo/goinfo_test.go b/goinfo/goinfo_test.go new file mode 100644 index 000000000..7e8665959 --- /dev/null +++ b/goinfo/goinfo_test.go @@ -0,0 +1,12 @@ +package goinfo_test + +import ( + "testing" + + "github.com/gookit/goutil/goinfo" + "github.com/gookit/goutil/testutil/assert" +) + +func TestGoVersion(t *testing.T) { + assert.NotEmpty(t, goinfo.GoVersion()) +} diff --git a/stdutil/stack.go b/goinfo/stack.go similarity index 93% rename from stdutil/stack.go rename to goinfo/stack.go index 701d1be74..1674a28a9 100644 --- a/stdutil/stack.go +++ b/goinfo/stack.go @@ -1,4 +1,4 @@ -package stdutil +package goinfo import ( "path" @@ -42,7 +42,7 @@ func GetCallStacks(all bool) []byte { // // returns: // -// github.com/gookit/goutil/stdutil_test.someFunc2(),stack_test.go:26 +// github.com/gookit/goutil/goinfo_test.someFunc2(),stack_test.go:26 func GetCallerInfo(skip int) string { skip++ // ignore current func cs := GetCallersInfo(skip, skip+1) @@ -62,6 +62,7 @@ func SimpleCallersInfo(skip, num int) []string { // GetCallersInfo returns an array of strings containing // the func name, file and line number of each stack frame leading. +// // NOTICE: max should > skip func GetCallersInfo(skip, max int) []string { var ( @@ -93,7 +94,7 @@ func GetCallersInfo(skip, max int) []string { if strings.ContainsRune(file, '/') { name = fc.Name() file = path.Base(file) - // eg: github.com/gookit/goutil/stdutil_test.someFunc2(),stack_test.go:26 + // eg: github.com/gookit/goutil/goinfo_test.someFunc2(),stack_test.go:26 callers = append(callers, name+"(),"+file+":"+strconv.Itoa(line)) } diff --git a/goinfo/stack_test.go b/goinfo/stack_test.go new file mode 100644 index 000000000..ea06572c9 --- /dev/null +++ b/goinfo/stack_test.go @@ -0,0 +1,45 @@ +package goinfo_test + +import ( + "fmt" + "testing" + + "github.com/gookit/goutil/goinfo" + "github.com/gookit/goutil/testutil/assert" +) + +func TestGetCallStacks(t *testing.T) { + msg := goinfo.GetCallStacks(false) + fmt.Println(string(msg)) + + fmt.Println("-------------full stacks-------------") + msg = goinfo.GetCallStacks(true) + fmt.Println(string(msg)) +} + +func TestGetCallersInfo(t *testing.T) { + cs := someFunc1() + assert.Len(t, cs, 1) + assert.Contains(t, cs[0], "goutil/goinfo_test.someFunc1(),stack_test.go") + + cs = someFunc2() + assert.Len(t, cs, 1) + assert.Contains(t, cs[0], "goutil/goinfo_test.someFunc2(),stack_test.go") + + loc := someFunc3() + assert.NotEmpty(t, loc) + assert.Contains(t, loc, "goutil/goinfo_test.someFunc3(),stack_test.go") + // dump.P(cs) +} + +func someFunc1() []string { + return goinfo.GetCallersInfo(1, 2) +} + +func someFunc2() []string { + return goinfo.SimpleCallersInfo(1, 1) +} + +func someFunc3() string { + return goinfo.GetCallerInfo(1) +} diff --git a/stdutil/README.md b/stdutil/README.md deleted file mode 100644 index a554d4689..000000000 --- a/stdutil/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Std Utils - -- some features - -## Install - -```bash -go get github.com/gookit/goutil/stdutils -``` - -## Go docs - -- [Go docs](https://pkg.go.dev/github.com/gookit/goutil/stdutils) - -## Usage - - -## Testings - -```shell -go test -v ./stdutils/... -``` - -Test limit by regexp: - -```shell -go test -v -run ^TestSetByKeys ./stdutils/... -``` diff --git a/stdutil/check.go b/stdutil/check.go deleted file mode 100644 index d1a167b94..000000000 --- a/stdutil/check.go +++ /dev/null @@ -1,135 +0,0 @@ -package stdutil - -import ( - "reflect" - "strings" - - "github.com/gookit/goutil/reflects" -) - -// IsNil value check -func IsNil(v any) bool { - if v == nil { - return true - } - return reflects.IsNil(reflect.ValueOf(v)) -} - -// IsEmpty value check -func IsEmpty(v any) bool { - if v == nil { - return true - } - return reflects.IsEmpty(reflect.ValueOf(v)) -} - -// IsFunc value -func IsFunc(val any) bool { - if val == nil { - return false - } - return reflect.TypeOf(val).Kind() == reflect.Func -} - -// IsEqual determines if two objects are considered equal. -// -// TIP: cannot compare function type -func IsEqual(src, dst any) bool { - if src == nil || dst == nil { - return src == dst - } - - // cannot compare function type - if IsFunc(src) || IsFunc(dst) { - return false - } - return reflects.IsEqual(src, dst) -} - -// Contains try loop over the data check if the data includes the element. -// alias of the IsContains -// -// TIP: only support types: string, map, array, slice -// -// map - check key exists -// string - check sub-string exists -// array,slice - check sub-element exists -func Contains(data, elem any) bool { - _, found := CheckContains(data, elem) - return found -} - -// IsContains try loop over the data check if the data includes the element. -// -// TIP: only support types: string, map, array, slice -// -// map - check key exists -// string - check sub-string exists -// array,slice - check sub-element exists -func IsContains(data, elem any) bool { - _, found := CheckContains(data, elem) - return found -} - -// CheckContains try loop over the data check if the data includes the element. -// -// TIP: only support types: string, map, array, slice -// -// map - check key exists -// string - check sub-string exists -// array,slice - check sub-element exists -// -// return (false, false) if impossible. -// return (true, false) if element was not found. -// return (true, true) if element was found. -func CheckContains(data, elem any) (valid, found bool) { - dataRv := reflect.ValueOf(data) - dataRt := reflect.TypeOf(data) - if dataRt == nil { - return false, false - } - - dataKind := dataRt.Kind() - - // string - if dataKind == reflect.String { - return true, strings.Contains(dataRv.String(), reflect.ValueOf(elem).String()) - } - - // map - if dataKind == reflect.Map { - mapKeys := dataRv.MapKeys() - for i := 0; i < len(mapKeys); i++ { - if reflects.IsEqual(mapKeys[i].Interface(), elem) { - return true, true - } - } - return true, false - } - - // array, slice - other return false - if dataKind != reflect.Slice && dataKind != reflect.Array { - return false, false - } - - for i := 0; i < dataRv.Len(); i++ { - if reflects.IsEqual(dataRv.Index(i).Interface(), elem) { - return true, true - } - } - return true, false -} - -// ValueIsEmpty reflect value check. -// -// Deprecated: please use reflects.IsEmpty() -func ValueIsEmpty(v reflect.Value) bool { - return reflects.IsEmpty(v) -} - -// ValueLen get reflect value length -// -// Deprecated: please use reflects.Len() -func ValueLen(v reflect.Value) int { - return reflects.Len(v) -} diff --git a/stdutil/check_test.go b/stdutil/check_test.go deleted file mode 100644 index 4537bedc1..000000000 --- a/stdutil/check_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package stdutil_test - -import ( - "reflect" - "testing" - - "github.com/gookit/goutil/stdutil" - "github.com/gookit/goutil/testutil/assert" -) - -func TestIsNil(t *testing.T) { - is := assert.New(t) - is.True(stdutil.IsNil(nil)) -} - -func TestIsEmpty(t *testing.T) { - is := assert.New(t) - - is.True(stdutil.IsEmpty(nil)) - is.False(stdutil.IsEmpty("abc")) -} - -func TestIsFunc(t *testing.T) { - is := assert.New(t) - is.False(stdutil.IsFunc(nil)) -} - -func TestIsEqual(t *testing.T) { - is := assert.New(t) - - is.True(stdutil.IsEqual("a", "a")) - is.True(stdutil.IsEqual([]string{"a"}, []string{"a"})) - is.True(stdutil.IsEqual(23, 23)) - is.True(stdutil.IsEqual(nil, nil)) - is.True(stdutil.IsEqual([]byte("abc"), []byte("abc"))) - - is.False(stdutil.IsEqual([]byte("abc"), "abc")) - is.False(stdutil.IsEqual(nil, 23)) - is.False(stdutil.IsEqual(stdutil.IsEmpty, 23)) -} - -func TestContains(t *testing.T) { - is := assert.New(t) - - is.True(stdutil.Contains("abc", "a")) - is.True(stdutil.Contains([]string{"abc", "def"}, "abc")) - is.True(stdutil.Contains(map[int]string{2: "abc", 4: "def"}, 4)) - - is.False(stdutil.Contains("abc", "def")) -} - -func TestValueIsEmpty(t *testing.T) { - is := assert.New(t) - - is.True(stdutil.ValueIsEmpty(reflect.ValueOf(nil))) - is.True(stdutil.ValueIsEmpty(reflect.ValueOf(""))) - - type T struct { - v any //lint:ignore U1000 for test - } - rv := reflect.ValueOf(T{}).Field(0) - is.True(stdutil.ValueIsEmpty(rv)) -} - -func TestValueLen(t *testing.T) { - is := assert.New(t) - tests := []any{ - "abc", - 123, - int8(123), int16(123), int32(123), int64(123), - uint8(123), uint16(123), uint32(123), uint64(123), - float32(123), float64(123), - []int{1, 2, 3}, []string{"a", "b", "c"}, - map[string]string{"k0": "v0", "k1": "v1", "k2": "v2"}, - } - - for _, sample := range tests { - is.Eq(3, stdutil.ValueLen(reflect.ValueOf(sample))) - } - - ptrArr := &[]string{"a", "b"} - is.Eq(2, stdutil.ValueLen(reflect.ValueOf(ptrArr))) - - is.Eq(-1, stdutil.ValueLen(reflect.ValueOf(nil))) -} diff --git a/stdutil/conv.go b/stdutil/conv.go deleted file mode 100644 index bd5e68dad..000000000 --- a/stdutil/conv.go +++ /dev/null @@ -1,50 +0,0 @@ -package stdutil - -import ( - "reflect" - - "github.com/gookit/goutil/reflects" - "github.com/gookit/goutil/strutil" -) - -// ToString always convert value to string, will ignore error -func ToString(v any) string { - s, _ := strutil.AnyToString(v, false) - return s -} - -// MustString convert value(basic type) to string, will panic on convert a complex type. -func MustString(v any) string { - s, err := strutil.AnyToString(v, true) - if err != nil { - panic(err) - } - return s -} - -// TryString try to convert a value to string -func TryString(v any) (string, error) { - return strutil.AnyToString(v, true) -} - -// BaseTypeVal convert custom type or intX,uintX,floatX to generic base type. -// -// intX/unitX => int64 -// floatX => float64 -// string => string -// -// returns int64,string,float or error -func BaseTypeVal(val any) (value any, err error) { - return reflects.BaseTypeVal(reflect.ValueOf(val)) -} - -// BaseTypeVal2 convert custom type or intX,uintX,floatX to generic base type. -// -// intX/unitX => int64 -// floatX => float64 -// string => string -// -// returns int64,string,float or error -func BaseTypeVal2(v reflect.Value) (value any, err error) { - return reflects.BaseTypeVal(v) -} diff --git a/stdutil/conv_test.go b/stdutil/conv_test.go deleted file mode 100644 index 472eec6c2..000000000 --- a/stdutil/conv_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package stdutil_test - -import ( - "encoding/json" - "reflect" - "testing" - "time" - - "github.com/gookit/goutil/comdef" - "github.com/gookit/goutil/stdutil" - "github.com/gookit/goutil/testutil/assert" -) - -func TestMustString(t *testing.T) { - assert.Eq(t, "23", stdutil.MustString(23)) - - assert.PanicsErrMsg(t, func() { - stdutil.MustString([]string{"a", "b"}) - }, comdef.ErrConvType.Error()) -} - -func TestToString(t *testing.T) { - assert.Eq(t, "23", stdutil.ToString(23)) - assert.Eq(t, "[a b]", stdutil.ToString([]string{"a", "b"})) -} - -func TestTryString(t *testing.T) { - s, err := stdutil.TryString(23) - assert.NoErr(t, err) - assert.Eq(t, "23", s) - - s, err = stdutil.TryString([]string{"a", "b"}) - assert.Eq(t, err, comdef.ErrConvType) - assert.Eq(t, "", s) -} - -func TestBaseTypeVal(t *testing.T) { - tests := []any{ - 2, - int8(2), int16(2), int32(2), int64(2), - uint(2), uint8(2), uint16(2), uint32(2), uint64(2), - time.Duration(2), - } - for _, el := range tests { - val, err := stdutil.BaseTypeVal(el) - assert.NoErr(t, err) - assert.Eq(t, int64(2), val) - } - - tests3 := []struct{ in, out any }{ - {"adc", "adc"}, - {"2", "2"}, - {json.Number("2"), "2"}, - } - for _, el := range tests3 { - val, err := stdutil.BaseTypeVal(el.in) - assert.NoErr(t, err) - assert.Eq(t, el.out, val) - } - - val, err := stdutil.BaseTypeVal(float32(2)) - assert.NoErr(t, err) - assert.Eq(t, float64(2), val) - - _, err = stdutil.BaseTypeVal([]int{2}) - assert.Err(t, err) - - val, err = stdutil.BaseTypeVal2(reflect.ValueOf(int32(2))) - assert.NoErr(t, err) - assert.Eq(t, int64(2), val) -} diff --git a/stdutil/gofunc_test.go b/stdutil/gofunc_test.go deleted file mode 100644 index 61016979c..000000000 --- a/stdutil/gofunc_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package stdutil_test - -import ( - "testing" - - "github.com/gookit/goutil/dump" - "github.com/gookit/goutil/stdutil" - "github.com/gookit/goutil/testutil/assert" -) - -func TestFuncName(t *testing.T) { - name := stdutil.FuncName(stdutil.PkgName) - assert.Eq(t, "github.com/gookit/goutil/stdutil.PkgName", name) - - name = stdutil.FuncName(stdutil.PanicIfErr) - assert.Eq(t, "github.com/gookit/goutil/stdutil.PanicIfErr", name) -} - -func TestPkgName(t *testing.T) { - name := stdutil.PkgName(stdutil.FuncName(stdutil.PanicIfErr)) - assert.Eq(t, "github.com/gookit/goutil/stdutil", name) -} - -func TestFullFcName_Parse(t *testing.T) { - fullName := stdutil.FuncName(stdutil.PanicIfErr) - - ffn := stdutil.FullFcName{FullName: fullName} - ffn.Parse() - assert.Eq(t, fullName, ffn.String()) - assert.Eq(t, "stdutil", ffn.PkgName()) - assert.Eq(t, "PanicIfErr", ffn.FuncName()) - assert.Eq(t, "github.com/gookit/goutil/stdutil", ffn.PkgPath()) - dump.P(ffn) - - st := stdutil.FullFcName{} - fullName = stdutil.FuncName(st.FuncName) - - ffn = stdutil.FullFcName{FullName: fullName} - ffn.Parse() - assert.Eq(t, "(*FullFcName).FuncName-fm", ffn.FuncName()) - dump.P(ffn) -} - -func TestCutFuncName(t *testing.T) { - fullName := stdutil.FuncName(stdutil.PanicIfErr) - - pkgPath, funcName := stdutil.CutFuncName(fullName) - assert.Eq(t, "PanicIfErr", funcName) - assert.Eq(t, "github.com/gookit/goutil/stdutil", pkgPath) -} diff --git a/stdutil/stack_test.go b/stdutil/stack_test.go deleted file mode 100644 index 334553b8f..000000000 --- a/stdutil/stack_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package stdutil_test - -import ( - "testing" - - "github.com/gookit/goutil/stdutil" - "github.com/gookit/goutil/testutil/assert" -) - -func TestGetCallersInfo(t *testing.T) { - cs := someFunc1() - assert.Len(t, cs, 1) - assert.Contains(t, cs[0], "goutil/stdutil_test.someFunc1(),stack_test.go") - - cs = someFunc2() - assert.Len(t, cs, 1) - assert.Contains(t, cs[0], "goutil/stdutil_test.someFunc2(),stack_test.go") - - loc := someFunc3() - assert.NotEmpty(t, loc) - assert.Contains(t, loc, "goutil/stdutil_test.someFunc3(),stack_test.go") - // dump.P(cs) -} - -func someFunc1() []string { - return stdutil.GetCallersInfo(1, 2) -} - -func someFunc2() []string { - return stdutil.SimpleCallersInfo(1, 1) -} - -func someFunc3() string { - return stdutil.GetCallerInfo(1) -} diff --git a/stdutil/stdutil.go b/stdutil/stdutil.go deleted file mode 100644 index a0382afe0..000000000 --- a/stdutil/stdutil.go +++ /dev/null @@ -1,34 +0,0 @@ -// Package stdutil provide some standard util functions for go. -package stdutil - -import ( - "fmt" - "runtime" -) - -// DiscardE discard error -func DiscardE(_ error) {} - -// PanicIfErr if error is not empty -func PanicIfErr(err error) { - if err != nil { - panic(err) - } -} - -// PanicIf if error is not empty -func PanicIf(err error) { - if err != nil { - panic(err) - } -} - -// Panicf format panic message use fmt.Sprintf -func Panicf(format string, v ...any) { - panic(fmt.Sprintf(format, v...)) -} - -// GoVersion get go runtime version. eg: "1.18.2" -func GoVersion() string { - return runtime.Version()[2:] -} diff --git a/stdutil/stdutil_test.go b/stdutil/stdutil_test.go deleted file mode 100644 index c2612d849..000000000 --- a/stdutil/stdutil_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package stdutil_test - -import ( - "fmt" - "testing" - - "github.com/gookit/goutil/errorx" - "github.com/gookit/goutil/stdutil" - "github.com/gookit/goutil/testutil/assert" -) - -func TestPanicIfErr(t *testing.T) { - stdutil.DiscardE(nil) - - stdutil.PanicIf(nil) - stdutil.PanicIfErr(nil) - - assert.Panics(t, func() { - stdutil.PanicIf(errorx.Raw("a error")) - }) - assert.Panics(t, func() { - stdutil.PanicIfErr(errorx.Raw("a error")) - }) -} - -func TestPanicf(t *testing.T) { - assert.Panics(t, func() { - stdutil.Panicf("hi %s", "inhere") - }) -} - -func TestGetCallStacks(t *testing.T) { - msg := stdutil.GetCallStacks(false) - fmt.Println(string(msg)) - - fmt.Println("-------------full stacks-------------") - msg = stdutil.GetCallStacks(true) - fmt.Println(string(msg)) -} - -func TestGoVersion(t *testing.T) { - assert.NotEmpty(t, stdutil.GoVersion()) -} diff --git a/stdutil/value.go b/stdutil/value.go deleted file mode 100644 index 05bf0a514..000000000 --- a/stdutil/value.go +++ /dev/null @@ -1,8 +0,0 @@ -package stdutil - -import ( - "github.com/gookit/goutil/structs" -) - -// Value data store, is alias of structs.Value -type Value = structs.Value