field: fix setting pointers. Closes ##16

This commit is contained in:
Fatih Arslan 2014-09-10 01:41:11 +03:00
parent ebbcf66cbe
commit 8624dc5ae3
2 changed files with 28 additions and 12 deletions

View File

@ -63,29 +63,23 @@ func (f *Field) Kind() reflect.Kind {
// settable (not addresable or not exported) or if the given value's type // settable (not addresable or not exported) or if the given value's type
// doesn't match the fields type. // doesn't match the fields type.
func (f *Field) Set(val interface{}) error { func (f *Field) Set(val interface{}) error {
// needed to make the field settable // we can't set unexported fields, so be sure this field is exported
v := reflect.Indirect(f.value)
if !f.IsExported() { if !f.IsExported() {
return errNotExported return errNotExported
} }
// do we get here? not sure... // do we get here? not sure...
if !v.CanSet() { if !f.value.CanSet() {
return errNotSettable return errNotSettable
} }
given := reflect.ValueOf(val) given := reflect.ValueOf(val)
if given.Kind() == reflect.Ptr { if f.value.Kind() != given.Kind() {
given = given.Elem() return fmt.Errorf("wrong kind. got: %s want: %s", given.Kind(), f.value.Kind())
} }
if v.Kind() != given.Kind() { f.value.Set(given)
return fmt.Errorf("wrong kind: %s want: %s", given.Kind(), v.Kind())
}
v.Set(given)
return nil return nil
} }

View File

@ -11,12 +11,18 @@ type Foo struct {
B int `structs:"y"` B int `structs:"y"`
C bool `json:"c"` C bool `json:"c"`
d string // not exported d string // not exported
E *Baz
x string `xml:"x"` // not exported, with tag x string `xml:"x"` // not exported, with tag
Y []string Y []string
Z map[string]interface{} Z map[string]interface{}
*Bar // embedded *Bar // embedded
} }
type Baz struct {
A string
B int
}
type Bar struct { type Bar struct {
E string E string
F int F int
@ -35,6 +41,7 @@ func newStruct() *Struct {
A: "gopher", A: "gopher",
C: true, C: true,
d: "small", d: "small",
E: nil,
Y: []string{"example"}, Y: []string{"example"},
Z: nil, Z: nil,
} }
@ -108,7 +115,22 @@ func TestField_Set(t *testing.T) {
t.Error(err) t.Error(err)
} }
// TODO: let's access a non addresable field, which should give an error baz := &Baz{
A: "helloWorld",
B: 42,
}
f = s.Field("E")
err = f.Set(baz)
if err != nil {
t.Error(err)
}
ba := s.Field("E").Value().(*Baz)
if ba.A != "helloWorld" {
t.Errorf("could not set baz. Got: %s Want: helloWorld", ba.A)
}
} }
func TestField(t *testing.T) { func TestField(t *testing.T) {