diff options
| author | apocelipes <seve3r@outlook.com> | 2025-09-24 03:23:03 +0000 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2025-09-29 07:53:08 -0700 |
| commit | d42d56b764f4c8b06aaa2de2dc9c1d2171e79490 (patch) | |
| tree | e98e91eea146b520559b05466405e50755c2f753 /src/encoding/xml/read.go | |
| parent | 6d51f932575284d6e78baa5e98f47f737a9f5b19 (diff) | |
| download | go-d42d56b764f4c8b06aaa2de2dc9c1d2171e79490.tar.xz | |
encoding/xml: make use of reflect.TypeAssert
To make the code more readable and improve performance:
goos: darwin
goarch: arm64
pkg: encoding/xml
cpu: Apple M4
│ old │ new │
│ sec/op │ sec/op vs base │
Marshal-10 1.902µ ± 1% 1.496µ ± 1% -21.37% (p=0.000 n=10)
Unmarshal-10 3.877µ ± 1% 3.418µ ± 2% -11.84% (p=0.000 n=10)
HTMLAutoClose-10 1.314µ ± 3% 1.333µ ± 1% ~ (p=0.270 n=10)
geomean 2.132µ 1.896µ -11.07%
│ old │ new │
│ B/op │ B/op vs base │
Marshal-10 5.570Ki ± 0% 5.570Ki ± 0% ~ (p=1.000 n=10) ¹
Unmarshal-10 7.586Ki ± 0% 7.555Ki ± 0% -0.41% (p=0.000 n=10)
HTMLAutoClose-10 3.496Ki ± 0% 3.496Ki ± 0% ~ (p=1.000 n=10) ¹
geomean 5.286Ki 5.279Ki -0.14%
¹ all samples are equal
│ old │ new │
│ allocs/op │ allocs/op vs base │
Marshal-10 23.00 ± 0% 23.00 ± 0% ~ (p=1.000 n=10) ¹
Unmarshal-10 185.0 ± 0% 184.0 ± 0% -0.54% (p=0.000 n=10)
HTMLAutoClose-10 93.00 ± 0% 93.00 ± 0% ~ (p=1.000 n=10) ¹
geomean 73.42 73.28 -0.18%
¹ all samples are equal
Updates #62121
Change-Id: Ie458e7458d4358c380374571d380ca3b65ca87bb
GitHub-Last-Rev: bb6bb3039328ca1d53ee3d56fd6597109ed76b09
GitHub-Pull-Request: golang/go#75483
Reviewed-on: https://go-review.googlesource.com/c/go/+/704215
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Diffstat (limited to 'src/encoding/xml/read.go')
| -rw-r--r-- | src/encoding/xml/read.go | 77 |
1 files changed, 46 insertions, 31 deletions
diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go index af25c20f06..d3cb74b2c4 100644 --- a/src/encoding/xml/read.go +++ b/src/encoding/xml/read.go @@ -255,28 +255,36 @@ func (d *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error { } val = val.Elem() } - if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) { + if val.CanInterface() { // This is an unmarshaler with a non-pointer receiver, // so it's likely to be incorrect, but we do what we're told. - return val.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr) + if unmarshaler, ok := reflect.TypeAssert[UnmarshalerAttr](val); ok { + return unmarshaler.UnmarshalXMLAttr(attr) + } } if val.CanAddr() { pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(unmarshalerAttrType) { - return pv.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr) + if pv.CanInterface() { + if unmarshaler, ok := reflect.TypeAssert[UnmarshalerAttr](pv); ok { + return unmarshaler.UnmarshalXMLAttr(attr) + } } } // Not an UnmarshalerAttr; try encoding.TextUnmarshaler. - if val.CanInterface() && val.Type().Implements(textUnmarshalerType) { + if val.CanInterface() { // This is an unmarshaler with a non-pointer receiver, // so it's likely to be incorrect, but we do what we're told. - return val.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value)) + if textUnmarshaler, ok := reflect.TypeAssert[encoding.TextUnmarshaler](val); ok { + return textUnmarshaler.UnmarshalText([]byte(attr.Value)) + } } if val.CanAddr() { pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) { - return pv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value)) + if pv.CanInterface() { + if textUnmarshaler, ok := reflect.TypeAssert[encoding.TextUnmarshaler](pv); ok { + return textUnmarshaler.UnmarshalText([]byte(attr.Value)) + } } } @@ -303,12 +311,7 @@ func (d *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error { return copyValue(val, []byte(attr.Value)) } -var ( - attrType = reflect.TypeFor[Attr]() - unmarshalerType = reflect.TypeFor[Unmarshaler]() - unmarshalerAttrType = reflect.TypeFor[UnmarshalerAttr]() - textUnmarshalerType = reflect.TypeFor[encoding.TextUnmarshaler]() -) +var attrType = reflect.TypeFor[Attr]() const ( maxUnmarshalDepth = 10000 @@ -352,27 +355,35 @@ func (d *Decoder) unmarshal(val reflect.Value, start *StartElement, depth int) e val = val.Elem() } - if val.CanInterface() && val.Type().Implements(unmarshalerType) { + if val.CanInterface() { // This is an unmarshaler with a non-pointer receiver, // so it's likely to be incorrect, but we do what we're told. - return d.unmarshalInterface(val.Interface().(Unmarshaler), start) + if unmarshaler, ok := reflect.TypeAssert[Unmarshaler](val); ok { + return d.unmarshalInterface(unmarshaler, start) + } } if val.CanAddr() { pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(unmarshalerType) { - return d.unmarshalInterface(pv.Interface().(Unmarshaler), start) + if pv.CanInterface() { + if unmarshaler, ok := reflect.TypeAssert[Unmarshaler](pv); ok { + return d.unmarshalInterface(unmarshaler, start) + } } } - if val.CanInterface() && val.Type().Implements(textUnmarshalerType) { - return d.unmarshalTextInterface(val.Interface().(encoding.TextUnmarshaler)) + if val.CanInterface() { + if textUnmarshaler, ok := reflect.TypeAssert[encoding.TextUnmarshaler](val); ok { + return d.unmarshalTextInterface(textUnmarshaler) + } } if val.CanAddr() { pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) { - return d.unmarshalTextInterface(pv.Interface().(encoding.TextUnmarshaler)) + if pv.CanInterface() { + if textUnmarshaler, ok := reflect.TypeAssert[encoding.TextUnmarshaler](pv); ok { + return d.unmarshalTextInterface(textUnmarshaler) + } } } @@ -453,7 +464,7 @@ func (d *Decoder) unmarshal(val reflect.Value, start *StartElement, depth int) e return UnmarshalError(e) } fv := finfo.value(sv, initNilPointers) - if _, ok := fv.Interface().(Name); ok { + if _, ok := reflect.TypeAssert[Name](fv); ok { fv.Set(reflect.ValueOf(start.Name)) } } @@ -578,20 +589,24 @@ Loop: } } - if saveData.IsValid() && saveData.CanInterface() && saveData.Type().Implements(textUnmarshalerType) { - if err := saveData.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil { - return err + if saveData.IsValid() && saveData.CanInterface() { + if textUnmarshaler, ok := reflect.TypeAssert[encoding.TextUnmarshaler](saveData); ok { + if err := textUnmarshaler.UnmarshalText(data); err != nil { + return err + } + saveData = reflect.Value{} } - saveData = reflect.Value{} } if saveData.IsValid() && saveData.CanAddr() { pv := saveData.Addr() - if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) { - if err := pv.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil { - return err + if pv.CanInterface() { + if textUnmarshaler, ok := reflect.TypeAssert[encoding.TextUnmarshaler](pv); ok { + if err := textUnmarshaler.UnmarshalText(data); err != nil { + return err + } + saveData = reflect.Value{} } - saveData = reflect.Value{} } } |
