Skip to content

Commit 4733710

Browse files
authored
Merge pull request #2 from RebirthLee/develop
add support types time.Time, time.Duration
2 parents 30640fe + b04f8a6 commit 4733710

File tree

10 files changed

+221
-30
lines changed

10 files changed

+221
-30
lines changed

.github/workflows/go.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ jobs:
1313
runs-on: ubuntu-latest
1414
steps:
1515

16-
- name: Set up Go 1.13
16+
- name: Set up Go 1.16.13
1717
uses: actions/setup-go@v1
1818
with:
19-
go-version: 1.13
19+
go-version: 1.16.13
2020
id: go
2121

2222
- name: Check out code into the Go module directory

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
.idea
2-
go.sum
32
# Binaries for programs and plugins
43
*.exe
54
*.exe~

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ go get github.com/rebirthlee/golang-default
3333
`def:"3.14,-10"`
3434
`def:"-3.14,3"`
3535
```
36+
37+
- `time.Duration`
38+
```go
39+
// calling time.ParseDuration
40+
`def:"1h"` // 1 * time.Hour
41+
```
42+
43+
- `time.Time`
44+
```go
45+
`def:"now"` // time.Now()
46+
`def:"+1h"` // time.Now().Add(1 * time.Hour)
47+
`def:"-1h"` // time.Now().Add(-1 * time.Hour)
48+
```
49+
3650
- Nested Struct
3751
```go
3852
type Parent struct {

default.go

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"reflect"
88
"strconv"
99
"strings"
10+
"time"
1011
)
1112

1213
const (
@@ -16,6 +17,11 @@ const (
1617
valueDiveLen = len(valueDive)
1718
)
1819

20+
var (
21+
timeDurationType = reflect.TypeOf(time.Duration(0))
22+
timeType = reflect.TypeOf(time.Time{})
23+
)
24+
1925
type structInitSelector func(v reflect.Value, visitedStruct map[reflect.Type]bool) error
2026

2127
func checkPtr(i interface{}) (reflect.Value, error) {
@@ -32,6 +38,7 @@ func Init(i interface{}) error {
3238
if err != nil {
3339
return err
3440
}
41+
defer callInit(v)
3542
return initStruct(v.Elem(), maybeInit, make(map[reflect.Type]bool))
3643
}
3744

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

5260
func initStruct(v reflect.Value, selector structInitSelector, visitedStruct map[reflect.Type]bool) error {
53-
defer callInit(v)
5461
if !v.CanSet() {
5562
return nil
5663
}
@@ -69,7 +76,7 @@ func justInit(v reflect.Value, visitedStruct map[reflect.Type]bool) error {
6976
fieldErrors := make([]*ErrorJustInitField, 0)
7077
t := v.Type()
7178
for i := 0; i < t.NumField(); i++ {
72-
if val, ok := t.Field(i).Tag.Lookup(tagNameDefault); val != "-" && ok {
79+
if val := t.Field(i).Tag.Get(tagNameDefault); val != "-" {
7380
if err := initField(v, v.Field(i), val, justInit, visitedStruct); err != nil {
7481
ft := t.Field(i)
7582
typeName := ft.Type.Name()
@@ -98,7 +105,7 @@ func justInit(v reflect.Value, visitedStruct map[reflect.Type]bool) error {
98105
func maybeInit(v reflect.Value, visitedStruct map[reflect.Type]bool) error {
99106
t := v.Type()
100107
for i := 0; i < t.NumField(); i++ {
101-
if val, ok := t.Field(i).Tag.Lookup(tagNameDefault); val != "-" && ok {
108+
if val := t.Field(i).Tag.Get(tagNameDefault); val != "-" {
102109
if err := initField(v, v.Field(i), val, maybeInit, visitedStruct); err != nil {
103110
return err
104111
}
@@ -114,17 +121,68 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
114121
return nil
115122
}
116123

117-
switch k := fieldVal.Kind(); k {
118-
case reflect.Invalid:
119-
return nil
124+
fieldType := fieldVal.Type()
125+
126+
//special type
127+
switch fieldType {
128+
case timeDurationType:
129+
if d, err := time.ParseDuration(defVal); err != nil {
130+
return err
131+
} else {
132+
fieldVal.Set(reflect.ValueOf(d))
133+
return nil
134+
}
135+
case timeType:
136+
if defVal == "now" {
137+
fieldVal.Set(reflect.ValueOf(time.Now()))
138+
return nil
139+
} else if strings.HasPrefix(defVal, "+") || strings.HasPrefix(defVal, "-") {
140+
d, err := time.ParseDuration(defVal)
141+
if err != nil {
142+
return err
143+
}
144+
145+
fieldVal.Set(reflect.ValueOf(time.Now().Add(d)))
146+
return nil
147+
}
148+
}
149+
150+
k := fieldVal.Kind()
151+
152+
// maybe Init function callable type
153+
switch k {
120154
case reflect.Ptr:
121155
elem := fieldVal.Elem()
122156
if elem.Kind() == reflect.Invalid {
123-
fieldVal.Set(reflect.New(fieldVal.Type().Elem()))
157+
fieldVal.Set(reflect.New(fieldType.Elem()))
124158
elem = fieldVal.Elem()
125159
}
126-
defer callInit(fieldVal)
160+
if elem.Kind() != reflect.Struct {
161+
defer callInit(fieldVal)
162+
}
127163
return initField(structVal, elem, defVal, selector, visitedStruct)
164+
case reflect.Struct:
165+
if fieldVal.CanAddr() {
166+
defer callInit(fieldVal)
167+
}
168+
169+
if defVal == valueDive {
170+
return initStruct(fieldVal, selector, visitedStruct)
171+
} else if defVal != "" {
172+
if err := jsonUnmarshalValue(fieldVal, defVal); err != nil {
173+
return err
174+
}
175+
}
176+
}
177+
178+
if defVal == "" {
179+
return nil
180+
}
181+
182+
// primitive type
183+
switch k {
184+
case reflect.Invalid:
185+
return nil
128186
case reflect.String:
129187
fieldVal.SetString(defVal)
130188
case reflect.Bool:
@@ -165,16 +223,16 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
165223
}
166224
case reflect.Interface:
167225
if defVal == "" {
168-
fieldVal.Set(reflect.Zero(fieldVal.Type()))
226+
fieldVal.Set(reflect.Zero(fieldType))
169227
} else if err := jsonUnmarshalValue(fieldVal, defVal); err != nil {
170228
return err
171229
}
172230
case reflect.Map:
173231
if strings.HasPrefix(defVal, valueDive+"{") && strings.HasSuffix(defVal, "}") {
174-
keyType := fieldVal.Type().Key()
175-
valType := fieldVal.Type().Elem()
232+
keyType := fieldType.Key()
233+
valType := fieldType.Elem()
176234

177-
fieldVal.Set(reflect.MakeMap(fieldVal.Type()))
235+
fieldVal.Set(reflect.MakeMap(fieldType))
178236

179237
tmp := defVal[valueDiveLen+1:len(defVal)-1]
180238
flag := byte(0x00)
@@ -237,12 +295,6 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
237295
} else if err := jsonUnmarshalValue(fieldVal, defVal); err != nil {
238296
return err
239297
}
240-
case reflect.Struct:
241-
if defVal == valueDive {
242-
return initStruct(fieldVal, selector, visitedStruct)
243-
} else if err := jsonUnmarshalValue(fieldVal, defVal); err != nil {
244-
return err
245-
}
246298
case reflect.Slice:
247299
if strings.HasPrefix(defVal, valueDive+"(") {
248300
tmp := defVal[valueDiveLen+1:]
@@ -295,7 +347,7 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
295347
}
296348
val = val[1:]
297349

298-
fieldVal.Set(reflect.MakeSlice(fieldVal.Type(), ln, cp))
350+
fieldVal.Set(reflect.MakeSlice(fieldType, ln, cp))
299351
for i := 0; i < ln; i++ {
300352
if err := initField(structVal, fieldVal.Index(i), val, selector, visitedStruct); err != nil {
301353
return err
@@ -326,7 +378,7 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
326378
} else if i, err := strconv.Atoi(defVal); err != nil {
327379
return err
328380
} else {
329-
fieldVal.Set(reflect.MakeChan(fieldVal.Type(), i))
381+
fieldVal.Set(reflect.MakeChan(fieldType, i))
330382
}
331383
case reflect.Func:
332384
srcFunc, ok := funcMap[defVal]
@@ -346,7 +398,7 @@ func initField(structVal reflect.Value, fieldVal reflect.Value, defVal string, s
346398
if srcType.Kind() != reflect.Func {
347399
return errors.New("return value must be function type")
348400
}
349-
vType := fieldVal.Type()
401+
vType := fieldType
350402
if vType.NumIn() != srcType.NumIn() {
351403
return errors.New("args count not equal")
352404
} else if vType.NumOut() != srcType.NumOut() {

example/interface/main.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
def "github.com/rebirthlee/golang-default"
6+
)
7+
8+
type InitString string
9+
10+
type Sample struct {
11+
ExportField string `def:"export field"`
12+
notExportField string
13+
StringField *InitString
14+
}
15+
16+
func (i *InitString) Init() {
17+
fmt.Printf("InitString(%p) call Init\n", i)
18+
*i = "Hello String Field"
19+
}
20+
21+
func (s *Sample) Init() {
22+
fmt.Printf("Sample(%p) call Init\n", s)
23+
s.notExportField = "not export field"
24+
}
25+
26+
func main() {
27+
28+
{
29+
// New
30+
i, err := def.New(Sample{})
31+
if err == nil {
32+
s := i.(*Sample)
33+
showFields(s)
34+
}
35+
}
36+
37+
{
38+
// MustNew
39+
s := def.MustNew(Sample{}).(*Sample)
40+
showFields(s)
41+
}
42+
43+
{
44+
// JustNew
45+
i, err := def.JustNew(Sample{})
46+
if err == nil {
47+
s := i.(*Sample)
48+
showFields(s)
49+
}
50+
}
51+
52+
{
53+
// Init
54+
s := Sample{}
55+
if err := def.Init(&s); err != nil {
56+
// ...err
57+
fmt.Println("Init, Handle Error")
58+
} else {
59+
showFields(&s)
60+
}
61+
}
62+
63+
{
64+
// MustInit
65+
s := Sample{}
66+
def.MustInit(&s)
67+
showFields(&s)
68+
}
69+
70+
{
71+
// JustInit
72+
s := Sample{}
73+
if err := def.JustInit(&s); err != nil {
74+
// ...err
75+
fmt.Println("JustInit, Handle Error")
76+
} else {
77+
showFields(&s)
78+
}
79+
}
80+
}
81+
82+
func showFields(s *Sample) {
83+
fmt.Printf("Struct Address : %p\n", s)
84+
fmt.Println("p.ExportField :", s.ExportField)
85+
fmt.Println("p.notExportField :", s.notExportField)
86+
fmt.Printf("p.StringField : %p\n", s.StringField)
87+
fmt.Println("*p.StringField :", *s.StringField)
88+
println()
89+
println()
90+
}

example/simple/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@ package main
33
import (
44
"fmt"
55
"github.com/rebirthlee/golang-default"
6+
"time"
67
)
78

89
type Person struct {
910
Age int `def:"20"`
1011
Name string `def:"rebirth lee"`
1112
PocketName *string `def:"bitcoin"`
13+
AliveTime time.Duration `def:"175200h"`
14+
CreateAt time.Time `def:"now"`
15+
After1Hour time.Time `def:"+1h"`
16+
Before1Hour time.Time `def:"-1h"`
1217
}
1318

1419
func main() {

go.mod

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
module github.com/rebirthlee/golang-default
22

3-
go 1.13
3+
go 1.16
44

5-
require github.com/stretchr/testify v1.5.1
5+
require (
6+
github.com/davecgh/go-spew v1.1.1 // indirect
7+
github.com/stretchr/testify v1.7.0
8+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
9+
)

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7+
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
8+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
9+
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
10+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
11+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
12+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
13+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
14+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
15+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
16+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

new.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ func New(i interface{}) (interface{}, error) {
1313
}
1414

1515
func MustNew(i interface{}) interface{} {
16-
ref := reflect.New(reflect.TypeOf(i))
17-
defer callInit(ref)
18-
if err := initStruct(ref.Elem(), maybeInit, make(map[reflect.Type]bool)); err != nil {
16+
ret, err := New(i)
17+
if err != nil {
1918
panic(err)
2019
}
2120

22-
return ref.Interface()
21+
return ret
2322
}
2423

2524
func JustNew(i interface{}) (interface{}, error) {

0 commit comments

Comments
 (0)