diff --git a/field.go b/field.go index 1a21071..d65d9f8 100644 --- a/field.go +++ b/field.go @@ -44,3 +44,20 @@ func (f *Field) IsZero() bool { func (f *Field) Name() string { return f.field.Name } + +// Field returns the field from a nested struct. It panics if the nested struct +// is not exported or if the field was not found. +func (f *Field) Field(name string) *Field { + v := strctVal(f.value.Interface()) + t := v.Type() + + field, ok := t.FieldByName(name) + if !ok { + panic("field not found") + } + + return &Field{ + field: field, + value: v.FieldByName(name), + } +} diff --git a/field_test.go b/field_test.go index d42d5af..c850643 100644 --- a/field_test.go +++ b/field_test.go @@ -149,3 +149,27 @@ func TestField_Name(t *testing.T) { t.Errorf("Fields 'A' field should have the name 'A'") } } + +func TestField_Field(t *testing.T) { + s := newStruct() + + e := s.Field("Bar").Field("E") + + val, ok := e.Value().(string) + if !ok { + t.Error("The value of the field 'e' inside 'Bar' struct should be string") + } + + if val != "example" { + t.Errorf("The value of 'e' should be 'example, got: %s", val) + } + + defer func() { + err := recover() + if err == nil { + t.Error("Field of a non existing nested struct should panic") + } + }() + + _ = s.Field("Bar").Field("e") +}