diff --git a/README.md b/README.md index 944ced5..4f2b513 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ s := &Server{ #### ToMap() -Convert to a `map[string]interface{}` +Convert a struct to a `map[string]interface{}` ```go m := structure.ToMap(s) @@ -39,8 +39,8 @@ fmt.Printf("%#v", m) #### ToSlice() -Convert to a `[]interface{}`. Slice values are **sorted** by default according -to the field names. +Convert the values of a struct to a `[]interface{}`. Slice values are +**sorted** by default according to the field names. ```go m := structure.ToSlice(s) @@ -49,6 +49,18 @@ m := structure.ToSlice(s) fmt.Printf("%#v", m) ``` +#### Fields() + +Convert the fields of a struct to a `[]string`. Slice values are **sorted** by +default according to the field names. + +```go +m := structure.Fields(s) + +// prints: []string{"Enabled", "ID", "Name"} +fmt.Printf("%#v", m) +``` + #### IsStruct() Check if it's a struct or a pointer to struct diff --git a/structure.go b/structure.go index 0fb99e3..5871b74 100644 --- a/structure.go +++ b/structure.go @@ -74,7 +74,8 @@ func ToSlice(s interface{}) []interface{} { } -// Fields returns a sorted slice of field names. +// Fields returns a sorted slice of field names. Note that only exported +// fields of a struct can be accessed, non exported fields will be neglected. func Fields(s interface{}) []string { m := ToMap(s) diff --git a/structure_example_test.go b/structure_example_test.go index 4653b98..1243c95 100644 --- a/structure_example_test.go +++ b/structure_example_test.go @@ -1,6 +1,9 @@ package structure -import "fmt" +import ( + "fmt" + "time" +) func ExampleToMap() { type Server struct { @@ -73,3 +76,24 @@ func ExampleToSlice() { // Output: // []interface {}{false, 135790, "Fatih"} } + +func ExampleFields() { + type Access struct { + Name string + LastAccessed time.Time + Number int + } + + s := &Access{ + Name: "Fatih", + LastAccessed: time.Now(), + Number: 1234567, + } + + m := Fields(s) + + // note that the output is sorted according to the field names + fmt.Printf("%#v\n", m) + // Output: + // []string{"LastAccessed", "Name", "Number"} +} diff --git a/structure_test.go b/structure_test.go index 8067b4b..57c3d2f 100644 --- a/structure_test.go +++ b/structure_test.go @@ -115,6 +115,10 @@ func TestToSlice(t *testing.T) { s := ToSlice(T) + if typ := reflect.TypeOf(s).Kind(); typ != reflect.Slice { + t.Errorf("ToSlice should return a slice type, got: %v", typ) + } + inSlice := func(val interface{}) bool { for _, v := range s { if reflect.DeepEqual(v, val) { @@ -130,3 +134,36 @@ func TestToSlice(t *testing.T) { } } } + +func TestFields(t *testing.T) { + var T = struct { + A string + B int + C bool + }{ + A: "a-value", + B: 2, + C: true, + } + + s := Fields(T) + + if len(s) != 3 { + t.Errorf("Fields should return a slice of len 3, got: %d", len(s)) + } + + inSlice := func(val string) bool { + for _, v := range s { + if reflect.DeepEqual(v, val) { + return true + } + } + return false + } + + for _, val := range []string{"A", "B", "C"} { + if !inSlice(val) { + t.Errorf("Fields should have the value %v", val) + } + } +}