From cee42ca53b1ceb9035bd7cc87ed772ff7e7eeda1 Mon Sep 17 00:00:00 2001 From: Ugorji Nwoke Date: Wed, 13 Jun 2012 16:24:09 -0400 Subject: [PATCH] [release-branch.go1] text/template: exec should accept interface value as valid. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit ««« backport 4c05c319570b text/template: exec should accept interface value as valid. Currently, if you pass some data to a template as an interface (e.g. interface{}) and extract that value that value as a parameter for a function, it fails, saying wrong type. This is because it is only looking at the interface type, not the interface content. This CL uses the underlying content as the parameter to the func. Fixes #3642. R=golang-dev, r, r CC=golang-dev https://golang.org/cl/6218052 »»» --- src/pkg/text/template/exec.go | 7 +++++++ src/pkg/text/template/exec_test.go | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/src/pkg/text/template/exec.go b/src/pkg/text/template/exec.go index feb434a3be..aba21ce28f 100644 --- a/src/pkg/text/template/exec.go +++ b/src/pkg/text/template/exec.go @@ -518,6 +518,13 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu } } if !value.Type().AssignableTo(typ) { + if value.Kind() == reflect.Interface && !value.IsNil() { + value = value.Elem() + if value.Type().AssignableTo(typ) { + return value + } + // fallthrough + } // Does one dereference or indirection work? We could do more, as we // do with method receivers, but that gets messy and method receivers // are much more constrained, so it makes more sense there than here. diff --git a/src/pkg/text/template/exec_test.go b/src/pkg/text/template/exec_test.go index 37d25f470c..f4ae50f0ee 100644 --- a/src/pkg/text/template/exec_test.go +++ b/src/pkg/text/template/exec_test.go @@ -311,6 +311,7 @@ var execTests = []execTest{ {".VariadicFuncInt", "{{call .VariadicFuncInt 33 `he` `llo`}}", "33=", tVal, true}, {"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", tVal, true}, {"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true}, + {"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true}, // Erroneous function calls (check args). {".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false}, @@ -507,6 +508,10 @@ func vfunc(V, *V) string { return "vfunc" } +func stringer(s fmt.Stringer) string { + return s.String() +} + func testExecute(execTests []execTest, template *Template, t *testing.T) { b := new(bytes.Buffer) funcs := FuncMap{ @@ -516,6 +521,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) { "typeOf": typeOf, "vfunc": vfunc, "zeroArgs": zeroArgs, + "stringer": stringer, } for _, test := range execTests { var tmpl *Template -- 2.50.0