structure: remove returning error, it should panic just like reflect
package
This commit is contained in:
parent
68345fdc8f
commit
afdeeccc8b
10
README.md
10
README.md
@ -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)
|
||||
|
||||
51
structure.go
51
structure.go
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user