Writing the README. Handling a few more cases, adding more tests.

This commit is contained in:
spf13 2014-04-05 15:18:23 -04:00
parent 6796452c69
commit 559d57776b
3 changed files with 157 additions and 74 deletions

View File

@ -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
Dont 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 doesnt 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
youll 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

View File

@ -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"})

151
caste.go
View File

@ -53,6 +53,84 @@ func ToBoolE(i interface{}) (bool, bool) {
return false, false return false, false
} }
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 {
return float64(v), true
} else {
jww.ERROR.Printf("Unable to Cast %#v to float", i)
jww.ERROR.Println(err)
}
default:
jww.ERROR.Printf("Unable to Cast %#v to float", i)
}
return 0.0, false
}
func ToIntE(i interface{}) (int, bool) {
switch s := i.(type) {
case int:
return s, true
case int64:
return int(s), true
case int32:
return int(s), true
case int16:
return int(s), true
case int8:
return int(s), true
case string:
v, err := strconv.ParseInt(s, 0, 0)
if err == nil {
return int(v), true
} else {
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)
}
return 0, false
}
func ToStringE(i interface{}) (string, bool) {
switch s := i.(type) {
case string:
return s, true
case float64:
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:
jww.ERROR.Printf("Unable to Cast %#v to string", i)
}
return "", false
}
func ToStringMapStringE(i interface{}) (map[string]string, bool) { func ToStringMapStringE(i interface{}) (map[string]string, bool) {
var m = map[string]string{} var m = map[string]string{}
@ -98,79 +176,6 @@ func ToStringSliceE(i interface{}) ([]string, bool) {
return a, true 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 {
return float64(v), true
} else {
jww.ERROR.Printf("Unable to Cast %#v to float", i)
jww.ERROR.Println(err)
}
default:
jww.ERROR.Printf("Unable to Cast %#v to float", i)
}
return 0.0, false
}
func ToIntE(i interface{}) (int, bool) {
switch s := i.(type) {
case int:
return s, true
case int64:
return int(s), true
case int32:
return int(s), true
case int16:
return int(s), true
case int8:
return int(s), true
case string:
v, err := strconv.ParseInt(s, 0, 0)
if err == nil {
return int(v), true
} else {
jww.ERROR.Printf("Unable to Cast %#v to int", i)
jww.ERROR.Println(err)
}
case bool:
if bool(s) {
return 1, true
} else {
return 0, true
}
default:
jww.ERROR.Printf("Unable to Cast %#v to int", i)
}
return 0, false
}
func ToStringE(i interface{}) (string, bool) {
switch s := i.(type) {
case string:
return s, true
case float64:
return strconv.FormatFloat(i.(float64), 'f', -1, 64), true
case int:
return strconv.FormatInt(int64(i.(int)), 10), true
case nil:
return "", true
default:
jww.ERROR.Printf("Unable to Cast %#v to string", i)
}
return "", false
}
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,