-
Notifications
You must be signed in to change notification settings - Fork 183
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: structs - InitDefaults() can init a struct by default tag
- Loading branch information
Showing
2 changed files
with
99 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,86 @@ | ||
package structs | ||
|
||
import "github.com/gookit/goutil/internal/comfunc" | ||
import ( | ||
"errors" | ||
"reflect" | ||
|
||
// ToMap simple convert structs to map by reflect | ||
func ToMap(st interface{}) map[string]interface{} { | ||
mp, _ := comfunc.TryStructToMap(st) | ||
return mp | ||
} | ||
"github.com/gookit/goutil/reflects" | ||
) | ||
|
||
// MapStruct simple copy src struct value to dst struct | ||
// func MapStruct(srcSt, dstSt interface{}) { | ||
// // TODO | ||
// } | ||
|
||
// TryToMap simple convert structs to map by reflect | ||
func TryToMap(st interface{}) (map[string]interface{}, error) { | ||
return comfunc.TryStructToMap(st) | ||
const defaultInitTag = "default" | ||
|
||
// InitOptions struct | ||
type InitOptions struct { | ||
TagName string | ||
} | ||
|
||
// MustToMap alis of TryToMap, but will panic on error | ||
func MustToMap(st interface{}) map[string]interface{} { | ||
mp, err := comfunc.TryStructToMap(st) | ||
if err != nil { | ||
panic(err) | ||
// InitDefaults init struct default value by field "default" tag. | ||
// | ||
// Example: | ||
// | ||
// type User1 struct { | ||
// Name string `default:"inhere"` | ||
// Age int32 `default:"30"` | ||
// } | ||
// | ||
// u1 := &User1{} | ||
// err = structs.InitDefaults(u1, nil) | ||
// fmt.Printf("%+v\n", u1) | ||
// // Output: {Name:inhere Age:30} | ||
func InitDefaults(ptr interface{}, opt *InitOptions) error { | ||
rv := reflect.ValueOf(ptr) | ||
if rv.Kind() != reflect.Ptr { | ||
return errors.New("must be provider an pointer") | ||
} | ||
|
||
rv = rv.Elem() | ||
if rv.Kind() != reflect.Struct { | ||
return errors.New("must be provider an struct") | ||
} | ||
return mp | ||
|
||
if opt == nil { | ||
opt = &InitOptions{TagName: defaultInitTag} | ||
} else if opt.TagName == "" { | ||
opt.TagName = defaultInitTag | ||
} | ||
|
||
return initDefaults(rv, opt.TagName) | ||
} | ||
|
||
// MapStruct simple copy src struct value to dst struct | ||
// func MapStruct(srcSt, dstSt interface{}) { | ||
// // TODO | ||
// } | ||
func initDefaults(rv reflect.Value, tagName string) error { | ||
rt := rv.Type() | ||
|
||
for i := 0; i < rt.NumField(); i++ { | ||
ft := rt.Field(i) | ||
// skip don't exported field | ||
if ft.Name[0] >= 'a' && ft.Name[0] <= 'z' { | ||
continue | ||
} | ||
|
||
fv := rv.Field(i) | ||
if fv.Kind() == reflect.Struct { | ||
err := initDefaults(fv, tagName) | ||
if err != nil { | ||
return err | ||
} | ||
continue | ||
} | ||
|
||
tagVal, ok := ft.Tag.Lookup(tagName) | ||
if ok && tagVal != "" && fv.CanSet() { | ||
val, err := reflects.ValueByKind(tagVal, fv.Kind()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fv.Set(val) | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters