From ca506a75fe031c824fa5076de97d332d814f1967 Mon Sep 17 00:00:00 2001 From: Asdine El Hrychy Date: Wed, 1 Jun 2016 11:26:46 +0200 Subject: [PATCH] Fix set value on nested field --- field.go | 11 ++++++++++- structs_test.go | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/field.go b/field.go index ad705f0..e697832 100644 --- a/field.go +++ b/field.go @@ -117,7 +117,16 @@ func (f *Field) Field(name string) *Field { // FieldOk returns the field from a nested struct. The boolean returns whether // the field was found (true) or not (false). func (f *Field) FieldOk(name string) (*Field, bool) { - v := strctVal(f.value.Interface()) + value := &f.value + // value must be settable so we need to make sure it holds the address of the + // variable and not a copy, so we can pass the pointer to strctVal instead of a + // copy (which is not assigned to any variable, hence not settable). + // see "https://blog.golang.org/laws-of-reflection#TOC_8." + if f.value.Kind() != reflect.Ptr { + a := f.value.Addr() + value = &a + } + v := strctVal(value.Interface()) t := v.Type() field, ok := t.FieldByName(name) diff --git a/structs_test.go b/structs_test.go index b1b05a1..0196246 100644 --- a/structs_test.go +++ b/structs_test.go @@ -1022,6 +1022,28 @@ func TestNestedNilPointer(t *testing.T) { _ = Map(personWithDogWithCollar) // Doesn't panic } +func TestSetValueOnNestedField(t *testing.T) { + type Base struct { + ID int + } + + type User struct { + Base + Name string + } + + u := User{} + s := New(&u) + f := s.Field("Base").Field("ID") + err := f.Set(10) + if err != nil { + t.Errorf("Error %v", err) + } + if f.Value().(int) != 10 { + t.Errorf("Value should be equal to 10, got %v", f.Value()) + } +} + type Person struct { Name string Age int