yaegi
yaegi copied to clipboard
Yaegi panics when using a func in a template FuncMap
The following program sample.go
triggers a panic:
package main
import (
"bytes"
"html/template"
)
var str = `{{ stringOr .Data "test" }}`
func main() {
tmpl, err := template.New("test").
Funcs(template.FuncMap{
"stringOr": stringOr,
}).
Parse(str)
if err != nil {
println(err.Error())
return
}
data := map[string]interface{}{"Data": ""}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, data); err != nil {
println(err.Error())
return
}
println(buf.String())
}
func stringOr(v, def string) string {
if v == "" {
return def
}
return v
}
Expected result:
$ go run ./sample.go
test
Got:
$ yaegi ./sample.go
./_test/test.go:11:15: panic
value for stringOr not a function
goroutine 1 [running]:
runtime/debug.Stack(0x1, 0xc0001fec00, 0x40)
/usr/local/Cellar/go/1.15.2/libexec/src/runtime/debug/stack.go:24 +0x9f
github.com/traefik/yaegi/interp.(*Interpreter).eval.func1(0xc000113d08)
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/interp/interp.go:451 +0xc5
panic(0x19bbec0, 0xc00049a0d0)
/usr/local/Cellar/go/1.15.2/libexec/src/runtime/panic.go:969 +0x175
github.com/traefik/yaegi/interp.runCfg.func1(0xc0002466e0, 0xc0001c9e00)
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/interp/run.go:124 +0x217
panic(0x19bbec0, 0xc00049a0d0)
/usr/local/Cellar/go/1.15.2/libexec/src/runtime/panic.go:969 +0x175
text/template.addValueFuncs(0xc000494630, 0xc000494690)
/usr/local/Cellar/go/1.15.2/libexec/src/text/template/funcs.go:92 +0x4c9
text/template.(*Template).Funcs(0xc0002e70c0, 0xc000494690, 0x0)
/usr/local/Cellar/go/1.15.2/libexec/src/text/template/template.go:174 +0x9b
html/template.(*Template).Funcs(0xc000494660, 0xc000494690, 0x0)
/usr/local/Cellar/go/1.15.2/libexec/src/html/template/template.go:344 +0x39
reflect.Value.call(0x1abe7e0, 0xc0001aac50, 0x1a93, 0x1ae7731, 0x4, 0xc00047b4a0, 0x1, 0x1, 0x18, 0xc00047b4a0, ...)
/usr/local/Cellar/go/1.15.2/libexec/src/reflect/value.go:475 +0x8c7
reflect.Value.Call(0x1abe7e0, 0xc0001aac50, 0x1a93, 0xc00047b4a0, 0x1, 0x1, 0x1ae4ca0, 0x1a12401, 0xc00047b4a0)
/usr/local/Cellar/go/1.15.2/libexec/src/reflect/value.go:336 +0xb9
github.com/traefik/yaegi/interp.callBin.func1(0x1abe7e0, 0xc0001aac50, 0x1a93, 0xc00047b4a0, 0x1, 0x1, 0x15, 0x19e64a0, 0xc00049a070)
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/interp/run.go:1078 +0x65
github.com/traefik/yaegi/interp.callBin.func10(0xc0002466e0, 0xc000498000)
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/interp/run.go:1225 +0x1c2
github.com/traefik/yaegi/interp.runCfg(0xc0001c9e00, 0xc0002466e0)
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/interp/run.go:130 +0x6e
github.com/traefik/yaegi/interp.(*Interpreter).run(0xc000374000, 0xc0001c9000, 0xc000246640)
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/interp/run.go:108 +0x2af
github.com/traefik/yaegi/interp.(*Interpreter).eval(0xc000374000, 0xc0002f5680, 0x20d, 0x7ffeefbff966, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/interp/interp.go:543 +0x809
github.com/traefik/yaegi/interp.(*Interpreter).EvalPath(0xc000374000, 0x7ffeefbff966, 0xf, 0xc0002f5400, 0x20d, 0x0, 0x0, 0xc000478000)
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/interp/interp.go:392 +0xfa
main.runFile(0xc000374000, 0x7ffeefbff966, 0xf, 0xc0001accc0, 0x1)
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/cmd/yaegi/run.go:113 +0xae
main.run(0xc0001941a0, 0x1, 0x1, 0x1b2f318, 0x19cd9e0)
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/cmd/yaegi/run.go:77 +0x725
main.main()
/Users/nrwiersma/Go/src/github.com/traefik/yaegi/cmd/yaegi/yaegi.go:119 +0x2ff
run: value for stringOr not a function
exit status 1
Just retested it, and it works with v0.12.0
Hi @mvertes, sorry for replying to a closed issue.
I encountered the same problem while using map[string]interface{}
instead of template.FuncMap
:
package main
import (
"bytes"
"html/template"
)
var str = `{{ stringOr .Data "test" }}`
func main() {
tmpl, err := template.New("test").
- Funcs(template.FuncMap{
+ Funcs(map[string]interface{}{
"stringOr": stringOr,
}).
Parse(str)
if err != nil {
println(err.Error())
return
}
data := map[string]interface{}{"Data": ""}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, data); err != nil {
println(err.Error())
return
}
println(buf.String())
}
func stringOr(v, def string) string {
if v == "" {
return def
}
return v
}
Got:
$ yaegi ./sample.go
./sample.go:11:15: panic
run: value for stringOr not a function
goroutine 1 [running]:
runtime/debug.Stack()
/usr/local/go/src/runtime/debug/stack.go:24 +0x65
github.com/traefik/yaegi/interp.(*Interpreter).Execute.func1()
/Users/russellluo/Labs/learn_go/projects/pkg/mod/github.com/traefik/[email protected]/interp/program.go:141 +0x94
panic({0x19296a0, 0xc000207e00})
/usr/local/go/src/runtime/panic.go:838 +0x207
github.com/traefik/yaegi/interp.runCfg.func1()
/Users/russellluo/Labs/learn_go/projects/pkg/mod/github.com/traefik/[email protected]/interp/run.go:192 +0x145
panic({0x19296a0, 0xc000207e00})
/usr/local/go/src/runtime/panic.go:838 +0x207
text/template.addValueFuncs(0x10bb965?, 0x1c25540?)
/usr/local/go/src/text/template/funcs.go:95 +0x314
text/template.(*Template).Funcs(0xc0002112c0, 0x1?)
/usr/local/go/src/text/template/template.go:181 +0x15c
html/template.(*Template).Funcs(0xc0004b2e40, 0x106ce99?)
/usr/local/go/src/html/template/template.go:346 +0x25
reflect.Value.call({0x1a268a0?, 0xc000208788?, 0x1011a25?}, {0x1a46745, 0x4}, {0xc000204c78, 0x1, 0xc0004a1948?})
/usr/local/go/src/reflect/value.go:556 +0x845
reflect.Value.Call({0x1a268a0?, 0xc000208788?, 0x1053f52?}, {0xc000204c78, 0x1, 0x1})
/usr/local/go/src/reflect/value.go:339 +0xbf
github.com/traefik/yaegi/interp.callBin.func2({0x1a268a0?, 0xc000208788?, 0xc0002087b8?}, {0xc000204c78?, 0xc0004b2e70?, 0xc000495968?})
...
reopen it, due to above test