@@ -1,4 +1,72 @@ | |||||
cast | cast | ||||
==== | ==== | ||||
easy casting from one type to another in Go | |||||
Easy and safe casting from one type to another in Go | |||||
Don’t Panic! ... Cast | |||||
## What is Cast? | |||||
Cast is a library to convert between different go types in a consistent and easy way. | |||||
Cast provides simple functions to easily convert a number to a string, an | |||||
interface into a bool, etc. Cast does this intelligently when an obvious | |||||
conversion is possible. It doesn’t make any attempts to guess what you meant, | |||||
for example you can only convert a string to an int when it is a string | |||||
representation of an int such as “8”. Cast was developed for use in | |||||
[Hugo](http://hugo.spf13.com), a website engine which uses YAML, TOML or JSON | |||||
for meta data. | |||||
## Why use Cast? | |||||
When working with dynamic data in Go you often need to cast or convert the data | |||||
from one type into another. Cast goes beyond just using type assertion (though | |||||
it uses that when possible) to provide a very straightforward and convenient | |||||
library. | |||||
If you are working with interfaces to handle things like dynamic content | |||||
you’ll need an easy way to convert an interface into a given type. This | |||||
is the library for you. | |||||
If you are taking in data from YAML, TOML or JSON or other formats which lack | |||||
full types, then Cast is the library for you. | |||||
## Usage | |||||
Cast provides a handful of To_____ methods. These methods will always return | |||||
the desired type. **If input is provided that will not convert to that type, the | |||||
0 or nil value for that type will be returned**. | |||||
Cast also provides identical methods To_____E. These return the same result as | |||||
the To_____ methods, plus an additional bool which tells you if it successfully | |||||
converted. Using these methods you can tell the difference between when the | |||||
input matched the zero value or when the conversion failed and the zero value | |||||
was returned. | |||||
The following examples are merely a sample of what is available. Please review | |||||
the code for a complete set. | |||||
### Example ‘ToString’: | |||||
cast.ToString("mayonegg") // "mayonegg" | |||||
cast.ToString(8) // "8" | |||||
cast.ToString(8.31) // "8.31" | |||||
cast.ToString([]byte("one time")) // "one time" | |||||
cast.ToString(nil) // "" | |||||
var foo interface{} = "one more time" | |||||
cast.ToString(foo) // "one more time" | |||||
### Example ‘ToInt’: | |||||
cast.ToInt(8) // 8 | |||||
cast.ToInt(8.31) // 8 | |||||
cast.ToInt("8") // 8 | |||||
cast.ToInt(true) // 1 | |||||
cast.ToInt(false) // 0 | |||||
var eight interface{} = 8 | |||||
cast.ToInt(eight) // 8 | |||||
cast.ToInt(nil) // 0 | |||||
@@ -14,12 +14,22 @@ import ( | |||||
func TestToInt(t *testing.T) { | func TestToInt(t *testing.T) { | ||||
var eight interface{} = 8 | var eight interface{} = 8 | ||||
assert.Equal(t, ToInt(8), 8) | assert.Equal(t, ToInt(8), 8) | ||||
assert.Equal(t, ToInt(8.31), 8) | |||||
assert.Equal(t, ToInt("8"), 8) | assert.Equal(t, ToInt("8"), 8) | ||||
assert.Equal(t, ToInt(true), 1) | assert.Equal(t, ToInt(true), 1) | ||||
assert.Equal(t, ToInt(false), 0) | assert.Equal(t, ToInt(false), 0) | ||||
assert.Equal(t, ToInt(eight), 8) | assert.Equal(t, ToInt(eight), 8) | ||||
} | } | ||||
func TestToString(t *testing.T) { | |||||
var foo interface{} = "one more time" | |||||
assert.Equal(t, ToString(8), "8") | |||||
assert.Equal(t, ToString(8.12), "8.12") | |||||
assert.Equal(t, ToString([]byte("one time")), "one time") | |||||
assert.Equal(t, ToString(foo), "one more time") | |||||
assert.Equal(t, ToString(nil), "") | |||||
} | |||||
func TestMaps(t *testing.T) { | func TestMaps(t *testing.T) { | ||||
var taxonomies = map[interface{}]interface{}{"tag": "tags", "group": "groups"} | var taxonomies = map[interface{}]interface{}{"tag": "tags", "group": "groups"} | ||||
assert.Equal(t, ToStringMap(taxonomies), map[string]interface{}{"tag": "tags", "group": "groups"}) | assert.Equal(t, ToStringMap(taxonomies), map[string]interface{}{"tag": "tags", "group": "groups"}) | ||||
@@ -53,58 +53,12 @@ func ToBoolE(i interface{}) (bool, bool) { | |||||
return false, false | return false, false | ||||
} | } | ||||
func ToStringMapStringE(i interface{}) (map[string]string, bool) { | |||||
var m = map[string]string{} | |||||
switch v := i.(type) { | |||||
case map[interface{}]interface{}: | |||||
for k, val := range v { | |||||
m[ToString(k)] = ToString(val) | |||||
} | |||||
default: | |||||
return m, false | |||||
} | |||||
return m, true | |||||
} | |||||
func ToStringMapE(i interface{}) (map[string]interface{}, bool) { | |||||
var m = map[string]interface{}{} | |||||
switch v := i.(type) { | |||||
case map[interface{}]interface{}: | |||||
for k, val := range v { | |||||
m[ToString(k)] = val | |||||
} | |||||
default: | |||||
return m, false | |||||
} | |||||
return m, true | |||||
} | |||||
func ToStringSliceE(i interface{}) ([]string, bool) { | |||||
var a []string | |||||
switch v := i.(type) { | |||||
case []interface{}: | |||||
for _, u := range v { | |||||
a = append(a, ToString(u)) | |||||
} | |||||
default: | |||||
return a, false | |||||
} | |||||
return a, true | |||||
} | |||||
func ToFloat64E(i interface{}) (float64, bool) { | func ToFloat64E(i interface{}) (float64, bool) { | ||||
switch s := i.(type) { | switch s := i.(type) { | ||||
case float64: | case float64: | ||||
return s, true | return s, true | ||||
case float32: | case float32: | ||||
return float64(s), true | return float64(s), true | ||||
case string: | case string: | ||||
v, err := strconv.ParseFloat(s, 64) | v, err := strconv.ParseFloat(s, 64) | ||||
if err == nil { | if err == nil { | ||||
@@ -141,12 +95,16 @@ func ToIntE(i interface{}) (int, bool) { | |||||
jww.ERROR.Printf("Unable to Cast %#v to int", i) | jww.ERROR.Printf("Unable to Cast %#v to int", i) | ||||
jww.ERROR.Println(err) | jww.ERROR.Println(err) | ||||
} | } | ||||
case float64: | |||||
return int(s), true | |||||
case bool: | case bool: | ||||
if bool(s) { | if bool(s) { | ||||
return 1, true | return 1, true | ||||
} else { | } else { | ||||
return 0, true | return 0, true | ||||
} | } | ||||
case nil: | |||||
return 0, true | |||||
default: | default: | ||||
jww.ERROR.Printf("Unable to Cast %#v to int", i) | jww.ERROR.Printf("Unable to Cast %#v to int", i) | ||||
} | } | ||||
@@ -162,6 +120,8 @@ func ToStringE(i interface{}) (string, bool) { | |||||
return strconv.FormatFloat(i.(float64), 'f', -1, 64), true | return strconv.FormatFloat(i.(float64), 'f', -1, 64), true | ||||
case int: | case int: | ||||
return strconv.FormatInt(int64(i.(int)), 10), true | return strconv.FormatInt(int64(i.(int)), 10), true | ||||
case []byte: | |||||
return string(s), true | |||||
case nil: | case nil: | ||||
return "", true | return "", true | ||||
default: | default: | ||||
@@ -171,6 +131,51 @@ func ToStringE(i interface{}) (string, bool) { | |||||
return "", false | return "", false | ||||
} | } | ||||
func ToStringMapStringE(i interface{}) (map[string]string, bool) { | |||||
var m = map[string]string{} | |||||
switch v := i.(type) { | |||||
case map[interface{}]interface{}: | |||||
for k, val := range v { | |||||
m[ToString(k)] = ToString(val) | |||||
} | |||||
default: | |||||
return m, false | |||||
} | |||||
return m, true | |||||
} | |||||
func ToStringMapE(i interface{}) (map[string]interface{}, bool) { | |||||
var m = map[string]interface{}{} | |||||
switch v := i.(type) { | |||||
case map[interface{}]interface{}: | |||||
for k, val := range v { | |||||
m[ToString(k)] = val | |||||
} | |||||
default: | |||||
return m, false | |||||
} | |||||
return m, true | |||||
} | |||||
func ToStringSliceE(i interface{}) ([]string, bool) { | |||||
var a []string | |||||
switch v := i.(type) { | |||||
case []interface{}: | |||||
for _, u := range v { | |||||
a = append(a, ToString(u)) | |||||
} | |||||
default: | |||||
return a, false | |||||
} | |||||
return a, true | |||||
} | |||||
func StringToDate(s string) (time.Time, error) { | func StringToDate(s string) (time.Time, error) { | ||||
return parseDateWith(s, []string{ | return parseDateWith(s, []string{ | ||||
time.RFC3339, | time.RFC3339, | ||||