diff options
| author | Russ Cox <rsc@golang.org> | 2016-11-11 11:54:18 -0500 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2016-11-11 19:46:17 +0000 |
| commit | 39e3cbfff623d7941b519f9d35883ef3b74cbcd6 (patch) | |
| tree | fa596d8e2da51025a94b545b3a89c9fa4d4e4b9a /src/text/template/exec.go | |
| parent | fabb4115ed311ec4af19f87c2334e38497dbb8d0 (diff) | |
| download | go-39e3cbfff623d7941b519f9d35883ef3b74cbcd6.tar.xz | |
text/template: reintroduce implicit indirect of interface values in builtin funcs
CL 31462 made it possible to operate directly on reflect.Values
instead of always forcing a round trip to interface{} and back.
The round trip was losing addressability, which hurt users.
The round trip was also losing "interface-ness", which helped users.
That is, using reflect.ValueOf(v.Interface()) instead of v was doing
an implicit indirect any time v was itself an interface{} value: the result
was the reflect.Value for the underlying concrete value contained in the
interface, not the interface itself.
CL 31462 eliminated some "unnecessary" reflect.Value round trips
in order to preserve addressability, but in doing so it lost this implicit
indirection. This CL adds the indirection back.
It may help to compare the changes in this CL against funcs.go from CL 31462:
https://go-review.googlesource.com/#/c/31462/4/src/text/template/funcs.go
Everywhere CL 31462 changed 'v := reflect.ValueOf(x)' to 'v := x',
this CL changes 'v := x' to 'v := indirectInterface(x)'.
Fixes #17714.
Change-Id: I67cec4eb41fed1d56e1c19f12b0abbd0e59d35a2
Reviewed-on: https://go-review.googlesource.com/33139
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
Diffstat (limited to 'src/text/template/exec.go')
| -rw-r--r-- | src/text/template/exec.go | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/src/text/template/exec.go b/src/text/template/exec.go index 7db4a87d2e..49f15faacd 100644 --- a/src/text/template/exec.go +++ b/src/text/template/exec.go @@ -874,6 +874,20 @@ func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { return v, false } +// indirectInterface returns the concrete value in an interface value, +// or else the zero reflect.Value. +// That is, if v represents the interface value x, the result is the same as reflect.ValueOf(x): +// the fact that x was an interface value is forgotten. +func indirectInterface(v reflect.Value) reflect.Value { + if v.Kind() != reflect.Interface { + return v + } + if v.IsNil() { + return reflect.Value{} + } + return v.Elem() +} + // printValue writes the textual representation of the value to the output of // the template. func (s *state) printValue(n parse.Node, v reflect.Value) { |
