structure: add ToSlice() , closes #3
This commit is contained in:
parent
e10d13000f
commit
e8a7d20d51
13
README.md
13
README.md
@ -32,10 +32,21 @@ if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%#v", m)
|
||||
// prints: map[string]interface {}{"Name":"Arslan", "ID":123456, "Enabled":true}
|
||||
fmt.Printf("%#v", m)
|
||||
```
|
||||
|
||||
```go
|
||||
// convert it to a []interface{}. Slice values are sorted according to the
|
||||
// field names.
|
||||
m, err := structure.ToSlice(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// prints: []interface {}{true, 123456, "Arslan"}
|
||||
fmt.Printf("%#v", m)
|
||||
|
||||
```go
|
||||
// check if it's a struct or a pointer to struct
|
||||
if structure.IsStruct(s) {
|
||||
|
||||
39
structure.go
39
structure.go
@ -4,6 +4,7 @@ package structure
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// ErrNotStruct is returned when the passed value is not a struct
|
||||
@ -13,11 +14,11 @@ var ErrNotStruct = errors.New("not struct")
|
||||
// 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(in interface{}) (map[string]interface{}, error) {
|
||||
func ToMap(s interface{}) (map[string]interface{}, error) {
|
||||
out := make(map[string]interface{})
|
||||
|
||||
t := reflect.TypeOf(in)
|
||||
v := reflect.ValueOf(in)
|
||||
t := reflect.TypeOf(s)
|
||||
v := reflect.ValueOf(s)
|
||||
|
||||
// if pointer get the underlying element≤
|
||||
if t.Kind() == reflect.Ptr {
|
||||
@ -50,10 +51,38 @@ func ToMap(in interface{}) (map[string]interface{}, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
keys := make([]string, len(m))
|
||||
count := 0
|
||||
for k := range m {
|
||||
keys[count] = k
|
||||
count++
|
||||
}
|
||||
|
||||
sort.Strings(keys)
|
||||
|
||||
t := make([]interface{}, len(m))
|
||||
|
||||
for i, key := range keys {
|
||||
t[i] = m[key]
|
||||
}
|
||||
|
||||
return t, nil
|
||||
|
||||
}
|
||||
|
||||
// IsStruct returns true if the given variable is a struct or a pointer to
|
||||
// struct.
|
||||
func IsStruct(strct interface{}) bool {
|
||||
t := reflect.TypeOf(strct)
|
||||
func IsStruct(s interface{}) bool {
|
||||
t := reflect.TypeOf(s)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
@ -58,3 +58,27 @@ func ExampleToMap_tags() {
|
||||
// false
|
||||
|
||||
}
|
||||
|
||||
func ExampleToSlice() {
|
||||
type Server struct {
|
||||
Name string
|
||||
ID int32
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
s := &Server{
|
||||
Name: "Fatih",
|
||||
ID: 135790,
|
||||
Enabled: false,
|
||||
}
|
||||
|
||||
m, err := ToSlice(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// note that the output is sorted according to the field names
|
||||
fmt.Printf("%#v\n", m)
|
||||
// Output:
|
||||
// []interface {}{false, 135790, "Fatih"}
|
||||
}
|
||||
|
||||
@ -105,3 +105,36 @@ func TestStruct(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestToSlice(t *testing.T) {
|
||||
var T = struct {
|
||||
A string
|
||||
B int
|
||||
C bool
|
||||
}{
|
||||
A: "a-value",
|
||||
B: 2,
|
||||
C: true,
|
||||
}
|
||||
|
||||
s, err := ToSlice(T)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
inSlice := func(val interface{}) bool {
|
||||
for _, v := range s {
|
||||
if reflect.DeepEqual(v, val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
for _, val := range []interface{}{"a-value", 2, true} {
|
||||
if !inSlice(val) {
|
||||
t.Errorf("ToSlice should have the value %v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user