From e34cf80acbc2614ad8e7c0f4016da0ee782c7df5 Mon Sep 17 00:00:00 2001 From: Fatih Arslan Date: Thu, 7 Aug 2014 11:09:05 +0300 Subject: [PATCH] structure: fix mixed up indexes, fixes #8. Thanks @yrashk for reporting --- structure.go | 33 +++++++++++++++++---------------- structure_test.go | 21 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/structure.go b/structure.go index 4004a94..5bf0955 100644 --- a/structure.go +++ b/structure.go @@ -24,9 +24,9 @@ func Map(s interface{}) map[string]interface{} { v, fields := strctInfo(s) - for i, field := range fields { + for _, field := range fields { name := field.Name - val := v.Field(i) + val := v.FieldByName(name) var finalVal interface{} @@ -63,8 +63,8 @@ func Values(s interface{}) []interface{} { v, fields := strctInfo(s) t := make([]interface{}, 0) - for i := range fields { - val := v.Field(i) + for _, field := range fields { + val := v.FieldByName(field.Name) if IsStruct(val.Interface()) { // look out for embedded structs, and convert them to a // []interface{} to be added to the final values slice @@ -92,8 +92,9 @@ func Values(s interface{}) []interface{} { func IsZero(s interface{}) bool { v, fields := strctInfo(s) - for i := range fields { - val := v.Field(i) + for _, field := range fields { + val := v.FieldByName(field.Name) + if IsStruct(val.Interface()) { ok := IsZero(val.Interface()) if !ok { @@ -104,10 +105,10 @@ func IsZero(s interface{}) bool { } // zero value of the given field, such as "" for string, 0 for int - zero := reflect.Zero(v.Field(i).Type()).Interface() + zero := reflect.Zero(val.Type()).Interface() // current value of the given field - current := v.Field(i).Interface() + current := val.Interface() if !reflect.DeepEqual(current, zero) { return false @@ -129,8 +130,8 @@ func IsZero(s interface{}) bool { func HasZero(s interface{}) bool { v, fields := strctInfo(s) - for i := range fields { - val := v.Field(i) + for _, field := range fields { + val := v.FieldByName(field.Name) if IsStruct(val.Interface()) { ok := HasZero(val.Interface()) if ok { @@ -141,10 +142,10 @@ func HasZero(s interface{}) bool { } // zero value of the given field, such as "" for string, 0 for int - zero := reflect.Zero(v.Field(i).Type()).Interface() + zero := reflect.Zero(val.Type()).Interface() // current value of the given field - current := v.Field(i).Interface() + current := val.Interface() if reflect.DeepEqual(current, zero) { return true @@ -166,8 +167,8 @@ func Fields(s interface{}) []string { v, fields := strctInfo(s) keys := make([]string, 0) - for i, field := range fields { - val := v.Field(i) + for _, field := range fields { + val := v.FieldByName(field.Name) if IsStruct(val.Interface()) { // look out for embedded structs, and convert them to a // []string to be added to the final values slice @@ -214,8 +215,8 @@ func Name(s interface{}) string { func Has(s interface{}, fieldName string) bool { v, fields := strctInfo(s) - for i, field := range fields { - val := v.Field(i) + for _, field := range fields { + val := v.FieldByName(field.Name) if IsStruct(val.Interface()) { if ok := Has(val.Interface(), fieldName); ok { diff --git a/structure_test.go b/structure_test.go index b2e8838..28d56f4 100644 --- a/structure_test.go +++ b/structure_test.go @@ -19,6 +19,27 @@ func TestMapNonStruct(t *testing.T) { _ = Map(foo) } +func TestStructIndexes(t *testing.T) { + type C struct { + something int + Props map[string]interface{} + } + + defer func() { + err := recover() + if err != nil { + t.Error("Using mixed indexes should not panic") + } + }() + + // They should not panic + _ = Map(&C{}) + _ = Fields(&C{}) + _ = Values(&C{}) + _ = IsZero(&C{}) + _ = HasZero(&C{}) +} + func TestMap(t *testing.T) { var T = struct { A string