structure: remove returning error, it should panic just like reflect

package
This commit is contained in:
Fatih Arslan 2014-07-27 23:38:29 +03:00
parent 68345fdc8f
commit afdeeccc8b
4 changed files with 47 additions and 59 deletions

View File

@ -31,10 +31,7 @@ s := &Server{
Convert to a `map[string]interface{}`
```go
m, err := structure.ToMap(s)
if err != nil {
panic(err)
}
m := structure.ToMap(s)
// prints: map[string]interface {}{"Name":"Arslan", "ID":123456, "Enabled":true}
fmt.Printf("%#v", m)
@ -46,10 +43,7 @@ Convert to a `[]interface{}`. Slice values are **sorted** by default according
to the field names.
```go
m, err := structure.ToSlice(s)
if err != nil {
panic(err)
}
m := structure.ToSlice(s)
// prints: []interface {}{true, 123456, "Arslan"}
fmt.Printf("%#v", m)

View File

@ -2,19 +2,16 @@
package structure
import (
"errors"
"reflect"
"sort"
)
// ErrNotStruct is returned when the passed value is not a struct
var ErrNotStruct = errors.New("not struct")
// ToMap converts a struct to a map[string]interface{}. The default map key
// string is the struct fieldname but this can be changed by defining a
// "structure" tag key if needed. Note that only exported fields of a struct
// can be accessed, non exported fields will be neglected.
func ToMap(s interface{}) (map[string]interface{}, error) {
// ToMap converts the given s struct to a map[string]interface{}. The default
// map key names are the struct fieldnames but this can be changed by defining
// a "structure" tag key if needed. Note that only exported fields of a struct
// can be accessed, non exported fields will be neglected. It panics if s's
// kind is not struct.
func ToMap(s interface{}) map[string]interface{} {
out := make(map[string]interface{})
t := reflect.TypeOf(s)
@ -27,7 +24,7 @@ func ToMap(s interface{}) (map[string]interface{}, error) {
}
if t.Kind() != reflect.Struct {
return nil, ErrNotStruct
panic("not struct")
}
for i := 0; i < t.NumField(); i++ {
@ -48,17 +45,15 @@ func ToMap(s interface{}) (map[string]interface{}, error) {
out[name] = v.Field(i).Interface()
}
return out, nil
return out
}
// ToSlice converts a struct's field values to a []interface{}. Values are
// inserted and sorted according to the field names. Note that only exported
// fields of a struct can be accessed, non exported fields will be neglected.
func ToSlice(s interface{}) ([]interface{}, error) {
m, err := ToMap(s)
if err != nil {
return nil, err
}
// ToSlice converts the given s struct's field values to a []interface{}.
// Values are inserted and sorted according to the field names. Note that only
// exported fields of a struct can be accessed, non exported fields will be
// neglected. It panics if s's kind is not struct.
func ToSlice(s interface{}) []interface{} {
m := ToMap(s)
keys := make([]string, len(m))
count := 0
@ -75,10 +70,26 @@ func ToSlice(s interface{}) ([]interface{}, error) {
t[i] = m[key]
}
return t, nil
return t
}
// Fields returns a sorted slice of field names.
func Fields(s interface{}) []string {
m := ToMap(s)
keys := make([]string, len(m))
count := 0
for k := range m {
keys[count] = k
count++
}
sort.Strings(keys)
return keys
}
// IsStruct returns true if the given variable is a struct or a pointer to
// struct.
func IsStruct(s interface{}) bool {

View File

@ -15,10 +15,7 @@ func ExampleToMap() {
Enabled: true,
}
m, err := ToMap(s)
if err != nil {
panic(err)
}
m := ToMap(s)
fmt.Printf("%#v\n", m["Name"])
fmt.Printf("%#v\n", m["ID"])
@ -43,10 +40,7 @@ func ExampleToMap_tags() {
ID: 789012,
}
m, err := ToMap(s)
if err != nil {
panic(err)
}
m := ToMap(s)
// access them by the custom tags defined above
fmt.Printf("%#v\n", m["server_name"])
@ -72,10 +66,7 @@ func ExampleToSlice() {
Enabled: false,
}
m, err := ToSlice(s)
if err != nil {
panic(err)
}
m := ToSlice(s)
// note that the output is sorted according to the field names
fmt.Printf("%#v\n", m)

View File

@ -8,11 +8,15 @@ import (
func TestToMapNonStruct(t *testing.T) {
foo := []string{"foo"}
_, err := ToMap(foo)
if err == nil {
t.Error("ToMap shouldn't accept non struct types")
}
defer func() {
err := recover()
if err == nil {
t.Error("Passing a non struct into ToMap should panic")
}
}()
// this should panic. We are going to recover and and test it
_ = ToMap(foo)
}
func TestToMap(t *testing.T) {
@ -26,10 +30,7 @@ func TestToMap(t *testing.T) {
C: true,
}
a, err := ToMap(T)
if err != nil {
t.Error(err)
}
a := ToMap(T)
if typ := reflect.TypeOf(a).Kind(); typ != reflect.Map {
t.Errorf("ToMap should return a map type, got: %v", typ)
@ -69,19 +70,14 @@ func TestToMap_Tag(t *testing.T) {
C: true,
}
a, err := ToMap(T)
if err != nil {
t.Error(err)
}
a := ToMap(T)
inMap := func(key interface{}) bool {
for k := range a {
if reflect.DeepEqual(k, key) {
return true
}
}
return false
}
@ -117,10 +113,7 @@ func TestToSlice(t *testing.T) {
C: true,
}
s, err := ToSlice(T)
if err != nil {
t.Error(err)
}
s := ToSlice(T)
inSlice := func(val interface{}) bool {
for _, v := range s {
@ -128,7 +121,6 @@ func TestToSlice(t *testing.T) {
return true
}
}
return false
}