diff --git a/README.md b/README.md index 87fccf2..1dc3404 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,10 @@ m := structs.Map(server) // => ["gopher", 123456, true] v := structs.Values(server) +// Convert the names of a struct to a []string +// (see "Names methods" for more info about fields) +n := structs.Names(server) + // Convert the values of a struct to a []*Field // (see "Field methods" for more info about fields) f := structs.Fields(server) @@ -73,6 +77,7 @@ s := structs.New(server) m := s.Map() // Get a map[string]interface{} v := s.Values() // Get a []interface{} f := s.Fields() // Get a []*Field +n := s.Names() // Get a []string f := s.Field(name) // Get a *Field based on the given field name f, ok := s.FieldsOk(name) // Get a *Field based on the given field name n := s.Name() // Get the struct name diff --git a/structs.go b/structs.go index 47bf354..1c1f68b 100644 --- a/structs.go +++ b/structs.go @@ -171,6 +171,25 @@ func (s *Struct) Fields() []*Field { return getFields(s.value, s.TagName) } +// Names returns a slice of field names. A struct tag with the content of "-" +// ignores the checking of that particular field. Example: +// +// // Field is ignored by this package. +// Field bool `structs:"-"` +// +// It panics if s's kind is not struct. +func (s *Struct) Names() []string { + fields := getFields(s.value, s.TagName) + + names := make([]string, len(fields)) + + for i, field := range fields { + names[i] = field.Name() + } + + return names +} + func getFields(v reflect.Value, tagName string) []*Field { if v.Kind() == reflect.Ptr { v = v.Elem() @@ -387,6 +406,12 @@ func Fields(s interface{}) []*Field { return New(s).Fields() } +// Names returns a slice of field names. For more info refer to Struct types +// Names() method. It panics if s's kind is not struct. +func Names(s interface{}) []string { + return New(s).Names() +} + // IsZero returns true if all fields is equal to a zero value. For more info // refer to Struct types IsZero() method. It panics if s's kind is not struct. func IsZero(s interface{}) bool { diff --git a/structs_test.go b/structs_test.go index 02788b1..8326176 100644 --- a/structs_test.go +++ b/structs_test.go @@ -442,6 +442,39 @@ func TestValues_Anonymous(t *testing.T) { } } +func TestNames(t *testing.T) { + var T = struct { + A string + B int + C bool + }{ + A: "a-value", + B: 2, + C: true, + } + + s := Names(T) + + if len(s) != 3 { + t.Errorf("Names 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("Names should have the value %v", val) + } + } +} + func TestFields(t *testing.T) { var T = struct { A string