diff --git a/README.md b/README.md index 120a573..10f978c 100644 --- a/README.md +++ b/README.md @@ -73,3 +73,5 @@ the code for a complete set. cast.ToInt(eight) // 8 cast.ToInt(nil) // 0 + cast.Atoi("0890") // 890 + diff --git a/cast.go b/cast.go index 0cfe941..ccd0e99 100644 --- a/cast.go +++ b/cast.go @@ -6,7 +6,9 @@ // Package cast provides easy and safe casting in Go. package cast -import "time" +import ( + "time" +) // ToBool casts an interface to a bool type. func ToBool(i interface{}) bool { @@ -73,6 +75,11 @@ func ToInt(i interface{}) int { return v } +func Atoi(i interface{}) int { + v, _ := AtoiE(i) + return v +} + // ToUint casts an interface to a uint type. func ToUint(i interface{}) uint { v, _ := ToUintE(i) diff --git a/cast_test.go b/cast_test.go index dc8ba14..86cf7f4 100644 --- a/cast_test.go +++ b/cast_test.go @@ -161,6 +161,16 @@ func TestToIntE(t *testing.T) { func(v interface{}) interface{} { return ToInt(v) }, ) } +func TestAtoiE(t *testing.T) { + tests := createNumberTestSteps(int(0), int(1), int(8), int(-8), int(8), int(-8)) + tests = append(tests, testStep{input: "0890", expect: 890, iserr: false}) + runNumberTest( + qt.New(t), + tests, + func(v interface{}) (interface{}, error) { return AtoiE(v) }, + func(v interface{}) interface{} { return Atoi(v) }, + ) +} func TestToInt64E(t *testing.T) { tests := createNumberTestSteps(int64(0), int64(1), int64(8), int64(-8), int64(8), int64(-8)) diff --git a/caste.go b/caste.go index 514d759..b4bdc29 100644 --- a/caste.go +++ b/caste.go @@ -487,6 +487,57 @@ func ToIntE(i interface{}) (int, error) { } } +func AtoiE(i interface{}) (int, error) { + i = indirect(i) + + intv, ok := toInt(i) + if ok { + return intv, nil + } + + switch s := i.(type) { + case int64: + return int(s), nil + case int32: + return int(s), nil + case int16: + return int(s), nil + case int8: + return int(s), nil + case uint: + return int(s), nil + case uint64: + return int(s), nil + case uint32: + return int(s), nil + case uint16: + return int(s), nil + case uint8: + return int(s), nil + case float64: + return int(s), nil + case float32: + return int(s), nil + case string: + v, err := strconv.ParseInt(trimZeroDecimal(s), 10, 0) + if err == nil { + return int(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + case json.Number: + return ToIntE(string(s)) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) + } +} + // ToUintE casts an interface to a uint type. func ToUintE(i interface{}) (uint, error) { i = indirect(i)