From: Micah Stetson Date: Mon, 25 Jun 2012 20:03:18 +0000 (-0400) Subject: encoding/json: simplify (*decodeState).indirect X-Git-Tag: go1.1rc2~2886 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=51ff2ef409ef0e9b3748540e37ff378a9b8bcaea;p=gostls13.git encoding/json: simplify (*decodeState).indirect Removes an incorrect code comment and some superfluous variables. The comment I removed says that struct fields which implement Unmarshaler must be pointers, even if they're in an addressable struct. That's not the case, and there's already a test in decode_test.go that demonstrates as much. Encoding/json has quite a few assignments of reflect.Values to extra variables – things like "iv := v" when there's no need to make a copy. I think these are left over from a previous version of the reflect API. If they aren't wanted, I wouldn't mind going through the package and getting rid of the rest of them. R=rsc CC=golang-dev https://golang.org/cl/6318047 --- diff --git a/src/pkg/encoding/json/decode.go b/src/pkg/encoding/json/decode.go index 44dc5784be..eb9fa4a8ab 100644 --- a/src/pkg/encoding/json/decode.go +++ b/src/pkg/encoding/json/decode.go @@ -265,47 +265,32 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, v = v.Addr() } for { - var isUnmarshaler bool - if v.Type().NumMethod() > 0 { - // Remember that this is an unmarshaler, - // but wait to return it until after allocating - // the pointer (if necessary). - _, isUnmarshaler = v.Interface().(Unmarshaler) - } - // Load value from interface, but only if the result will be // usefully addressable. - if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() { - e := iv.Elem() + if v.Kind() == reflect.Interface && !v.IsNil() { + e := v.Elem() if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { v = e continue } } - pv := v - if pv.Kind() != reflect.Ptr { + if v.Kind() != reflect.Ptr { break } - if pv.Elem().Kind() != reflect.Ptr && decodingNull && pv.CanSet() { - return nil, pv + if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() { + break } - if pv.IsNil() { - pv.Set(reflect.New(pv.Type().Elem())) + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) } - if isUnmarshaler { - // Using v.Interface().(Unmarshaler) - // here means that we have to use a pointer - // as the struct field. We cannot use a value inside - // a pointer to a struct, because in that case - // v.Interface() is the value (x.f) not the pointer (&x.f). - // This is an unfortunate consequence of reflect. - // An alternative would be to look up the - // UnmarshalJSON method and return a FuncValue. - return v.Interface().(Unmarshaler), reflect.Value{} + if v.Type().NumMethod() > 0 { + if unmarshaler, ok := v.Interface().(Unmarshaler); ok { + return unmarshaler, reflect.Value{} + } } - v = pv.Elem() + v = v.Elem() } return nil, v }