mirror of
https://github.com/golang/go
synced 2024-11-20 02:14:46 -07:00
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
This commit is contained in:
parent
576d648b2a
commit
4f7c33cd5a
@ -520,6 +520,13 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !value.Type().AssignableTo(typ) {
|
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
|
// Does one dereference or indirection work? We could do more, as we
|
||||||
// do with method receivers, but that gets messy and method receivers
|
// do with method receivers, but that gets messy and method receivers
|
||||||
// are much more constrained, so it makes more sense there than here.
|
// are much more constrained, so it makes more sense there than here.
|
||||||
|
@ -314,6 +314,7 @@ var execTests = []execTest{
|
|||||||
{".VariadicFuncInt", "{{call .VariadicFuncInt 33 `he` `llo`}}", "33=<he+llo>", tVal, true},
|
{".VariadicFuncInt", "{{call .VariadicFuncInt 33 `he` `llo`}}", "33=<he+llo>", tVal, true},
|
||||||
{"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", 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},
|
{"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).
|
// Erroneous function calls (check args).
|
||||||
{".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false},
|
{".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false},
|
||||||
@ -512,6 +513,10 @@ func vfunc(V, *V) string {
|
|||||||
return "vfunc"
|
return "vfunc"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stringer(s fmt.Stringer) string {
|
||||||
|
return s.String()
|
||||||
|
}
|
||||||
|
|
||||||
func testExecute(execTests []execTest, template *Template, t *testing.T) {
|
func testExecute(execTests []execTest, template *Template, t *testing.T) {
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
funcs := FuncMap{
|
funcs := FuncMap{
|
||||||
@ -521,6 +526,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) {
|
|||||||
"typeOf": typeOf,
|
"typeOf": typeOf,
|
||||||
"vfunc": vfunc,
|
"vfunc": vfunc,
|
||||||
"zeroArgs": zeroArgs,
|
"zeroArgs": zeroArgs,
|
||||||
|
"stringer": stringer,
|
||||||
}
|
}
|
||||||
for _, test := range execTests {
|
for _, test := range execTests {
|
||||||
var tmpl *Template
|
var tmpl *Template
|
||||||
|
Loading…
Reference in New Issue
Block a user