Skip to content

Commit

Permalink
allow to use integer literals
Browse files Browse the repository at this point in the history
as defined in go1.13 and later
  • Loading branch information
licaonfee committed Jul 16, 2020
1 parent 0dea786 commit cb916d0
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 12 deletions.
23 changes: 12 additions & 11 deletions defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func Set(ptr interface{}) error {
}

func setField(field reflect.Value, defaultVal string) error {
const defaultBase = 0
if !field.CanSet() {
return nil
}
Expand All @@ -58,49 +59,49 @@ func setField(field reflect.Value, defaultVal string) error {
field.Set(reflect.ValueOf(val).Convert(field.Type()))
}
case reflect.Int:
if val, err := strconv.ParseInt(defaultVal, 10, 64); err == nil {
if val, err := strconv.ParseInt(defaultVal, defaultBase, 64); err == nil {
field.Set(reflect.ValueOf(int(val)).Convert(field.Type()))
}
case reflect.Int8:
if val, err := strconv.ParseInt(defaultVal, 10, 8); err == nil {
if val, err := strconv.ParseInt(defaultVal, defaultBase, 8); err == nil {
field.Set(reflect.ValueOf(int8(val)).Convert(field.Type()))
}
case reflect.Int16:
if val, err := strconv.ParseInt(defaultVal, 10, 16); err == nil {
if val, err := strconv.ParseInt(defaultVal, defaultBase, 16); err == nil {
field.Set(reflect.ValueOf(int16(val)).Convert(field.Type()))
}
case reflect.Int32:
if val, err := strconv.ParseInt(defaultVal, 10, 32); err == nil {
if val, err := strconv.ParseInt(defaultVal, defaultBase, 32); err == nil {
field.Set(reflect.ValueOf(int32(val)).Convert(field.Type()))
}
case reflect.Int64:
if val, err := time.ParseDuration(defaultVal); err == nil {
field.Set(reflect.ValueOf(val).Convert(field.Type()))
} else if val, err := strconv.ParseInt(defaultVal, 10, 64); err == nil {
} else if val, err := strconv.ParseInt(defaultVal, defaultBase, 64); err == nil {
field.Set(reflect.ValueOf(val).Convert(field.Type()))
}
case reflect.Uint:
if val, err := strconv.ParseUint(defaultVal, 10, 64); err == nil {
if val, err := strconv.ParseUint(defaultVal, defaultBase, 64); err == nil {
field.Set(reflect.ValueOf(uint(val)).Convert(field.Type()))
}
case reflect.Uint8:
if val, err := strconv.ParseUint(defaultVal, 10, 8); err == nil {
if val, err := strconv.ParseUint(defaultVal, defaultBase, 8); err == nil {
field.Set(reflect.ValueOf(uint8(val)).Convert(field.Type()))
}
case reflect.Uint16:
if val, err := strconv.ParseUint(defaultVal, 10, 16); err == nil {
if val, err := strconv.ParseUint(defaultVal, defaultBase, 16); err == nil {
field.Set(reflect.ValueOf(uint16(val)).Convert(field.Type()))
}
case reflect.Uint32:
if val, err := strconv.ParseUint(defaultVal, 10, 32); err == nil {
if val, err := strconv.ParseUint(defaultVal, defaultBase, 32); err == nil {
field.Set(reflect.ValueOf(uint32(val)).Convert(field.Type()))
}
case reflect.Uint64:
if val, err := strconv.ParseUint(defaultVal, 10, 64); err == nil {
if val, err := strconv.ParseUint(defaultVal, defaultBase, 64); err == nil {
field.Set(reflect.ValueOf(val).Convert(field.Type()))
}
case reflect.Uintptr:
if val, err := strconv.ParseUint(defaultVal, 10, 64); err == nil {
if val, err := strconv.ParseUint(defaultVal, defaultBase, 64); err == nil {
field.Set(reflect.ValueOf(uintptr(val)).Convert(field.Type()))
}
case reflect.Float32:
Expand Down
127 changes: 127 additions & 0 deletions defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,39 @@ type Sample struct {
String string `default:"hello"`
Duration time.Duration `default:"10s"`

IntOct int `default:"0o1"`
Int8Oct int8 `default:"0o10"`
Int16Oct int16 `default:"0o20"`
Int32Oct int32 `default:"0o40"`
Int64Oct int64 `default:"0o100"`
UintOct uint `default:"0o1"`
Uint8Oct uint8 `default:"0o10"`
Uint16Oct uint16 `default:"0o20"`
Uint32Oct uint32 `default:"0o40"`
Uint64Oct uint64 `default:"0o100"`

IntHex int `default:"0x1"`
Int8Hex int8 `default:"0x8"`
Int16Hex int16 `default:"0x10"`
Int32Hex int32 `default:"0x20"`
Int64Hex int64 `default:"0x40"`
UintHex uint `default:"0x1"`
Uint8Hex uint8 `default:"0x8"`
Uint16Hex uint16 `default:"0x10"`
Uint32Hex uint32 `default:"0x20"`
Uint64Hex uint64 `default:"0x40"`

IntBin int `default:"0b1"`
Int8Bin int8 `default:"0b1000"`
Int16Bin int16 `default:"0b10000"`
Int32Bin int32 `default:"0b100000"`
Int64Bin int64 `default:"0b1000000"`
UintBin uint `default:"0b1"`
Uint8Bin uint8 `default:"0b1000"`
Uint16Bin uint16 `default:"0b10000"`
Uint32Bin uint32 `default:"0b100000"`
Uint64Bin uint64 `default:"0b1000000"`

Struct Struct `default:"{}"`
StructPtr *Struct `default:"{}"`
Map map[string]int `default:"{}"`
Expand Down Expand Up @@ -182,6 +215,100 @@ func TestInit(t *testing.T) {
if sample.String != "hello" {
t.Errorf("it should initialize string")
}

if sample.IntOct != 0o1 {
t.Errorf("it should initialize int with octal literal")
}
if sample.Int8Oct != 0o10 {
t.Errorf("it should initialize int8 with octal literal")
}
if sample.Int16Oct != 0o20 {
t.Errorf("it should initialize int16 with octal literal")
}
if sample.Int32Oct != 0o40 {
t.Errorf("it should initialize int32 with octal literal")
}
if sample.Int64Oct != 0o100 {
t.Errorf("it should initialize int64 with octal literal")
}
if sample.UintOct != 0o1 {
t.Errorf("it should initialize uint with octal literal")
}
if sample.Uint8Oct != 0o10 {
t.Errorf("it should initialize uint8 with octal literal")
}
if sample.Uint16Oct != 0o20 {
t.Errorf("it should initialize uint16 with octal literal")
}
if sample.Uint32Oct != 0o40 {
t.Errorf("it should initialize uint32 with octal literal")
}
if sample.Uint64Oct != 0o100 {
t.Errorf("it should initialize uint64 with octal literal")
}

if sample.IntHex != 0x1 {
t.Errorf("it should initialize int with hexadecimal literal")
}
if sample.Int8Hex != 0x8 {
t.Errorf("it should initialize int8 with hexadecimal literal")
}
if sample.Int16Hex != 0x10 {
t.Errorf("it should initialize int16 with hexadecimal literal")
}
if sample.Int32Hex != 0x20 {
t.Errorf("it should initialize int32 with hexadecimal literal")
}
if sample.Int64Hex != 0x40 {
t.Errorf("it should initialize int64 with hexadecimal literal")
}
if sample.UintHex != 0x1 {
t.Errorf("it should initialize uint with hexadecimal literal")
}
if sample.Uint8Hex != 0x8 {
t.Errorf("it should initialize uint8 with hexadecimal literal")
}
if sample.Uint16Hex != 0x10 {
t.Errorf("it should initialize uint16 with hexadecimal literal")
}
if sample.Uint32Hex != 0x20 {
t.Errorf("it should initialize uint32 with hexadecimal literal")
}
if sample.Uint64Hex != 0x40 {
t.Errorf("it should initialize uint64 with hexadecimal literal")
}

if sample.IntBin != 0b1 {
t.Errorf("it should initialize int with binary literal")
}
if sample.Int8Bin != 0b1000 {
t.Errorf("it should initialize int8 with binary literal")
}
if sample.Int16Bin != 0b10000 {
t.Errorf("it should initialize int16 with binary literal")
}
if sample.Int32Bin != 0b100000 {
t.Errorf("it should initialize int32 with binary literal")
}
if sample.Int64Bin != 0b1000000 {
t.Errorf("it should initialize int64 with binary literal")
}
if sample.UintBin != 0b1 {
t.Errorf("it should initialize uint with binary literal")
}
if sample.Uint8Bin != 0b1000 {
t.Errorf("it should initialize uint8 with binary literal")
}
if sample.Uint16Bin != 0b10000 {
t.Errorf("it should initialize uint16 with binary literal")
}
if sample.Uint32Bin != 0b100000 {
t.Errorf("it should initialize uint32 with binary literal")
}
if sample.Uint64Bin != 0b1000000 {
t.Errorf("it should initialize uint64 with binary literal")
}

})

t.Run("complex types", func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/creasty/defaults

go 1.11
go 1.13

0 comments on commit cb916d0

Please sign in to comment.