@@ -1,4 +1,72 @@ | |||
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) { | |||
var eight interface{} = 8 | |||
assert.Equal(t, ToInt(8), 8) | |||
assert.Equal(t, ToInt(8.31), 8) | |||
assert.Equal(t, ToInt("8"), 8) | |||
assert.Equal(t, ToInt(true), 1) | |||
assert.Equal(t, ToInt(false), 0) | |||
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) { | |||
var taxonomies = map[interface{}]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 | |||
} | |||
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) { | |||
switch s := i.(type) { | |||
case float64: | |||
return s, true | |||
case float32: | |||
return float64(s), true | |||
case string: | |||
v, err := strconv.ParseFloat(s, 64) | |||
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.Println(err) | |||
} | |||
case float64: | |||
return int(s), true | |||
case bool: | |||
if bool(s) { | |||
return 1, true | |||
} else { | |||
return 0, true | |||
} | |||
case nil: | |||
return 0, true | |||
default: | |||
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 | |||
case int: | |||
return strconv.FormatInt(int64(i.(int)), 10), true | |||
case []byte: | |||
return string(s), true | |||
case nil: | |||
return "", true | |||
default: | |||
@@ -171,6 +131,51 @@ func ToStringE(i interface{}) (string, bool) { | |||
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) { | |||
return parseDateWith(s, []string{ | |||
time.RFC3339, | |||