Skip to content

Commit

Permalink
Merge pull request #2 from RebirthLee/develop
Browse files Browse the repository at this point in the history
add support types time.Time, time.Duration
  • Loading branch information
2rebi committed Jan 17, 2022
2 parents 30640fe + b04f8a6 commit 4733710
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 30 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:
runs-on: ubuntu-latest
steps:

- name: Set up Go 1.13
- name: Set up Go 1.16.13
uses: actions/setup-go@v1
with:
go-version: 1.13
go-version: 1.16.13
id: go

- name: Check out code into the Go module directory
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.idea
go.sum
# Binaries for programs and plugins
*.exe
*.exe~
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ go get github.com/rebirthlee/golang-default
`def:"3.14,-10"`
`def:"-3.14,3"`
```

- `time.Duration`
```go
// calling time.ParseDuration
`def:"1h"` // 1 * time.Hour
```

- `time.Time`
```go
`def:"now"` // time.Now()
`def:"+1h"` // time.Now().Add(1 * time.Hour)
`def:"-1h"` // time.Now().Add(-1 * time.Hour)
```

- Nested Struct
```go
type Parent struct {
Expand Down
94 changes: 73 additions & 21 deletions default.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"reflect"
"strconv"
"strings"
"time"
)

const (
Expand All @@ -16,6 +17,11 @@ const (
valueDiveLen = len(valueDive)
)

var (
timeDurationType = reflect.TypeOf(time.Duration(0))
timeType = reflect.TypeOf(time.Time{})
)

type structInitSelector func(v reflect.Value, visitedStruct map[reflect.Type]bool) error

func checkPtr(i interface{}) (reflect.Value, error) {
Expand All @@ -32,6 +38,7 @@ func Init(i interface{}) error {
if err != nil {
return err
}
defer callInit(v)
return initStruct(v.Elem(), maybeInit, make(map[reflect.Type]bool))
}

Expand All @@ -46,11 +53,11 @@ func JustInit(i interface{}) error {
if err != nil {
return err
}
defer callInit(v)
return initStruct(v.Elem(), justInit, make(map[reflect.Type]bool))
}

func initStruct(v reflect.Value, selector structInitSelector, visitedStruct map[reflect.Type]bool) error {
defer callInit(v)
if !v.CanSet() {
return nil
}
Expand All @@ -69,7 +76,7 @@ func justInit(v reflect.Value, visitedStruct map[reflect.Type]bool) error {
fieldErrors := make([]*ErrorJustInitField, 0)
t := v.Type()
for i := 0; i < t.NumField(); i++ {
if val, ok := t.Field(i).Tag.Lookup(tagNameDefault); val != "-" && ok {
if val := t.Field(i).Tag.Get(tagNameDefault); val != "-" {
if err := initField(v, v.Field(i), val, justInit, visitedStruct); err != nil {
ft := t.Field(i)
typeName := ft.Type.Name()
Expand Down Expand Up @@ -98,7 +105,7 @@ func justInit(v reflect.Value, visitedStruct map[reflect.Type]bool) error {
func maybeInit(v reflect.Value, visitedStruct map[reflect.Type]bool) error {
t := v.Type()
for i := 0; i < t.NumField(); i++ {
if val, ok := t.Field(i).Tag.Lookup(tagNameDefault); val != "-" && ok {
if val := t.Field(i).Tag.Get(tagNameDefault); val != "-" {
if err := initField(v, v.Field(i), val, maybeInit, visitedStruct); err != nil {
return err
}
Expand All @@ -114,17 +121,68 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
return nil
}

switch k := fieldVal.Kind(); k {
case reflect.Invalid:
return nil
fieldType := fieldVal.Type()

//special type
switch fieldType {
case timeDurationType:
if d, err := time.ParseDuration(defVal); err != nil {
return err
} else {
fieldVal.Set(reflect.ValueOf(d))
return nil
}
case timeType:
if defVal == "now" {
fieldVal.Set(reflect.ValueOf(time.Now()))
return nil
} else if strings.HasPrefix(defVal, "+") || strings.HasPrefix(defVal, "-") {
d, err := time.ParseDuration(defVal)
if err != nil {
return err
}

fieldVal.Set(reflect.ValueOf(time.Now().Add(d)))
return nil
}
}

k := fieldVal.Kind()

// maybe Init function callable type
switch k {
case reflect.Ptr:
elem := fieldVal.Elem()
if elem.Kind() == reflect.Invalid {
fieldVal.Set(reflect.New(fieldVal.Type().Elem()))
fieldVal.Set(reflect.New(fieldType.Elem()))
elem = fieldVal.Elem()
}
defer callInit(fieldVal)
if elem.Kind() != reflect.Struct {
defer callInit(fieldVal)
}
return initField(structVal, elem, defVal, selector, visitedStruct)
case reflect.Struct:
if fieldVal.CanAddr() {
defer callInit(fieldVal)
}

if defVal == valueDive {
return initStruct(fieldVal, selector, visitedStruct)
} else if defVal != "" {
if err := jsonUnmarshalValue(fieldVal, defVal); err != nil {
return err
}
}
}

if defVal == "" {
return nil
}

// primitive type
switch k {
case reflect.Invalid:
return nil
case reflect.String:
fieldVal.SetString(defVal)
case reflect.Bool:
Expand Down Expand Up @@ -165,16 +223,16 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
}
case reflect.Interface:
if defVal == "" {
fieldVal.Set(reflect.Zero(fieldVal.Type()))
fieldVal.Set(reflect.Zero(fieldType))
} else if err := jsonUnmarshalValue(fieldVal, defVal); err != nil {
return err
}
case reflect.Map:
if strings.HasPrefix(defVal, valueDive+"{") && strings.HasSuffix(defVal, "}") {
keyType := fieldVal.Type().Key()
valType := fieldVal.Type().Elem()
keyType := fieldType.Key()
valType := fieldType.Elem()

fieldVal.Set(reflect.MakeMap(fieldVal.Type()))
fieldVal.Set(reflect.MakeMap(fieldType))

tmp := defVal[valueDiveLen+1:len(defVal)-1]
flag := byte(0x00)
Expand Down Expand Up @@ -237,12 +295,6 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
} else if err := jsonUnmarshalValue(fieldVal, defVal); err != nil {
return err
}
case reflect.Struct:
if defVal == valueDive {
return initStruct(fieldVal, selector, visitedStruct)
} else if err := jsonUnmarshalValue(fieldVal, defVal); err != nil {
return err
}
case reflect.Slice:
if strings.HasPrefix(defVal, valueDive+"(") {
tmp := defVal[valueDiveLen+1:]
Expand Down Expand Up @@ -295,7 +347,7 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
}
val = val[1:]

fieldVal.Set(reflect.MakeSlice(fieldVal.Type(), ln, cp))
fieldVal.Set(reflect.MakeSlice(fieldType, ln, cp))
for i := 0; i < ln; i++ {
if err := initField(structVal, fieldVal.Index(i), val, selector, visitedStruct); err != nil {
return err
Expand Down Expand Up @@ -326,7 +378,7 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
} else if i, err := strconv.Atoi(defVal); err != nil {
return err
} else {
fieldVal.Set(reflect.MakeChan(fieldVal.Type(), i))
fieldVal.Set(reflect.MakeChan(fieldType, i))
}
case reflect.Func:
srcFunc, ok := funcMap[defVal]
Expand All @@ -346,7 +398,7 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
if srcType.Kind() != reflect.Func {
return errors.New("return value must be function type")
}
vType := fieldVal.Type()
vType := fieldType
if vType.NumIn() != srcType.NumIn() {
return errors.New("args count not equal")
} else if vType.NumOut() != srcType.NumOut() {
Expand Down
90 changes: 90 additions & 0 deletions example/interface/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package main

import (
"fmt"
def "github.com/rebirthlee/golang-default"
)

type InitString string

type Sample struct {
ExportField string `def:"export field"`
notExportField string
StringField *InitString
}

func (i *InitString) Init() {
fmt.Printf("InitString(%p) call Init\n", i)
*i = "Hello String Field"
}

func (s *Sample) Init() {
fmt.Printf("Sample(%p) call Init\n", s)
s.notExportField = "not export field"
}

func main() {

{
// New
i, err := def.New(Sample{})
if err == nil {
s := i.(*Sample)
showFields(s)
}
}

{
// MustNew
s := def.MustNew(Sample{}).(*Sample)
showFields(s)
}

{
// JustNew
i, err := def.JustNew(Sample{})
if err == nil {
s := i.(*Sample)
showFields(s)
}
}

{
// Init
s := Sample{}
if err := def.Init(&s); err != nil {
// ...err
fmt.Println("Init, Handle Error")
} else {
showFields(&s)
}
}

{
// MustInit
s := Sample{}
def.MustInit(&s)
showFields(&s)
}

{
// JustInit
s := Sample{}
if err := def.JustInit(&s); err != nil {
// ...err
fmt.Println("JustInit, Handle Error")
} else {
showFields(&s)
}
}
}

func showFields(s *Sample) {
fmt.Printf("Struct Address : %p\n", s)
fmt.Println("p.ExportField :", s.ExportField)
fmt.Println("p.notExportField :", s.notExportField)
fmt.Printf("p.StringField : %p\n", s.StringField)
fmt.Println("*p.StringField :", *s.StringField)
println()
println()
}
5 changes: 5 additions & 0 deletions example/simple/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ package main
import (
"fmt"
"github.com/rebirthlee/golang-default"
"time"
)

type Person struct {
Age int `def:"20"`
Name string `def:"rebirth lee"`
PocketName *string `def:"bitcoin"`
AliveTime time.Duration `def:"175200h"`
CreateAt time.Time `def:"now"`
After1Hour time.Time `def:"+1h"`
Before1Hour time.Time `def:"-1h"`
}

func main() {
Expand Down
8 changes: 6 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
module github.com/rebirthlee/golang-default

go 1.13
go 1.16

require github.com/stretchr/testify v1.5.1
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/stretchr/testify v1.7.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
7 changes: 3 additions & 4 deletions new.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ func New(i interface{}) (interface{}, error) {
}

func MustNew(i interface{}) interface{} {
ref := reflect.New(reflect.TypeOf(i))
defer callInit(ref)
if err := initStruct(ref.Elem(), maybeInit, make(map[reflect.Type]bool)); err != nil {
ret, err := New(i)
if err != nil {
panic(err)
}

return ref.Interface()
return ret
}

func JustNew(i interface{}) (interface{}, error) {
Expand Down
Loading

0 comments on commit 4733710

Please sign in to comment.