31
votes

It noticed a weird thing with Go templates when I try to use Funcs and FuncMap. The following code works as expected:

buffer := bytes.NewBufferString("")

funcMap := template.FuncMap{
    "label": strings.Title,
}

t, _ := template.New("alex").Funcs(funcMap).Parse("{{label \"alex\"}}") 

t.Execute(buffer, "")

return string(buffer.Bytes()) //=> "Alex"

But when I try to put the template in a file, it does not work (Execute() says: "alex" is an incomplete or empty template):

t, _ := template.New("alex").Funcs(funcMap).ParseFiles("template.html") 

With template.html:

{{label \"alex\"}}

Any idea why ? Is this a bug ? Are there simpler ways to use methods/functions in templates ?

3
First ideas are to check errors from Parse and Execute. Your code above ignores both.Sonia
Yeah I had checked Parse but not Execute. Execute says: ""alex" is an incomplete or empty template"Blacksad

3 Answers

34
votes

ParseFiles could probably use better documentation. A template object can have multiple templates in it and each one has a name. If you look at the implementation of ParseFiles, you see that it uses the filename as the template name inside of the template object. So, name your file the same as the template object, (probably not generally practical) or else use ExecuteTemplate instead of just Execute.

16
votes

Sonia's answer is technically correct but left me even more confused. Here's how I eventually got it working:

t, err := template.New("_base.html").Funcs(funcs).ParseFiles("../view/_base.html", "../view/home.html")
if err != nil {
    fmt.Fprint(w, "Error:", err)
    fmt.Println("Error:", err)
    return
}
err = t.Execute(w, data)
if err != nil {
    fmt.Fprint(w, "Error:", err)
    fmt.Println("Error:", err)
}

The name of the template is the bare filename of the template, not the complete path. Execute will execute the default template provided it's named to match, so there's no need to use ExecuteTemplate.

In this case, _base.html file is the outermost container, eg:

<!DOCTYPE html>
<html><body>
<h1>{{ template "title" }}</h1>
{{ template "content" }}
</body></html>

while home.html defines the specific parts:

{{ define "title" }}Home{{ end }}

{{ define "content" }}
Stuff
{{ end }}
0
votes

you need to first parse all the files and execute them .you cannot direclty access all the files .