Custom function is not working in template

I’ve the below that is working fine playground

package main

import (
	"html/template"
	"os"
)

func main() {
	tmpl := `
{{ $slice := mkSlice "a" 5 "b" }}
{{ range $slice }}
     {{ . }}
{{ end }}
`
	funcMap := map[string]interface{}{"mkSlice": mkSlice}
	t := template.New("").Funcs(template.FuncMap(funcMap))
	template.Must(t.Parse(tmpl))
	t.Execute(os.Stdout, nil)
}

func mkSlice(args ...interface{}) []interface{} {
	return args
}

But once I tried to run in from template file, nothing had been displayed, and no error had been recieved!

func mkSlice(args ...interface{}) []interface{} { // to ceate the array in the template
	return args
}

funcMap := map[string]interface{}{"mkSlice": mkSlice}
tmpl := template.New("").Funcs(template.FuncMap(funcMap))
template.Must(tmpl.ParseFiles("index.html"))
tmpl.Execute(w, nil)

And index.html is:

{{ $slice := mkSlice "a" 5 "b" }}
{{ range $slice }}
    <span> {{ . }} </span>
{{ end }}

any thought?

I got the solution at stackoverflow so sharing it here for the benefit of the community:
You don’t see any errors because you don’t check the error returned by tmpl.Execute(w, nil). When do check it:

if err := t.Execute(os.Stdout, nil); err != nil {
	panic(err)
}

You’ll see an output like:

panic: template: "" is an incomplete or empty template

The difference is that in the first case you used Template.Parse() method which:

… parses text as a template body for t.

Note that the template text you parse will be used for t itself!

In the second case you used Template.ParseFiles() which:

… parses the named files and associates the resulting templates with t. If an error occurs, parsing stops and the returned template is nil; otherwise it is t. There must be at least one file. Since the templates created by ParseFiles are named by the base names of the argument files, t should usually have the name of one of the (base) names of the files.

So in your first example t contains a single template, and that single template will be executed by Template.Execute().

In your second example t contains multiple associated templates, t itself being an empty template, and another, associated template named index.html. You may execute that template using Template.ExecuteTemplate():

if err := t.ExecuteTemplate(os.Stdout, "index.html", nil); err != nil {
	panic(err)
}

For more information, see:

1 Like