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)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("%#v", m)
|
|
||||||
// prints: map[string]interface {}{"Name":"Arslan", "ID":123456, "Enabled":true}
|
// 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
|
```go
|
||||||
// check if it's a struct or a pointer to struct
|
// check if it's a struct or a pointer to struct
|
||||||
if structure.IsStruct(s) {
|
if structure.IsStruct(s) {
|
||||||
|
|||||||
39
structure.go
39
structure.go
@ -4,6 +4,7 @@ package structure
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrNotStruct is returned when the passed value is not a struct
|
// 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
|
// 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
|
// "structure" tag key if needed. Note that only exported fields of a struct
|
||||||
// can be accessed, non exported fields will be neglected.
|
// 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{})
|
out := make(map[string]interface{})
|
||||||
|
|
||||||
t := reflect.TypeOf(in)
|
t := reflect.TypeOf(s)
|
||||||
v := reflect.ValueOf(in)
|
v := reflect.ValueOf(s)
|
||||||
|
|
||||||
// if pointer get the underlying element≤
|
// if pointer get the underlying element≤
|
||||||
if t.Kind() == reflect.Ptr {
|
if t.Kind() == reflect.Ptr {
|
||||||
@ -50,10 +51,38 @@ func ToMap(in interface{}) (map[string]interface{}, error) {
|
|||||||
return out, nil
|
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
|
// IsStruct returns true if the given variable is a struct or a pointer to
|
||||||
// struct.
|
// struct.
|
||||||
func IsStruct(strct interface{}) bool {
|
func IsStruct(s interface{}) bool {
|
||||||
t := reflect.TypeOf(strct)
|
t := reflect.TypeOf(s)
|
||||||
if t.Kind() == reflect.Ptr {
|
if t.Kind() == reflect.Ptr {
|
||||||
t = t.Elem()
|
t = t.Elem()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,3 +58,27 @@ func ExampleToMap_tags() {
|
|||||||
// false
|
// 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