Template and custom function; panic: function not defined

go

Solution

IIRC, template functions map must be defined by `.Funcs` before parsing the template. The below code seems to work.

package main

import (
        "html/template"
        "io/ioutil"
        "net/http"
        "strconv"
)

var funcMap = template.FuncMap{
        "humanSize": humanSize,
}

const tmpl = `
<html><body>
    {{range .}}
    <div>
        <span>{{.Name}}</span>
        <span>{{humanSize .Size}}</span>
    </div>
    {{end}}
</body></html>`

var tmplGet = template.Must(template.New("").Funcs(funcMap).Parse(tmpl))

func humanSize(s int64) string {
        return strconv.FormatInt(s/int64(1000), 10) + " KB"
}

func getPageHandler(w http.ResponseWriter, r *http.Request) {
        files, err := ioutil.ReadDir(".")
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
        }

        if err := tmplGet.Execute(w, files); err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
        }
}

func main() {
        http.HandleFunc("/", getPageHandler)
        http.ListenAndServe(":8080", nil)
}

Problem

Using `html/template` I am trying to use one of my own functions inside a template. Unfortunately I am unable to use the function map feature of go's templates. All I get is the following error: ``` % go run test.go panic: template: tmpl.html:5: function "humanSize" not defined [...] ``` The reduced testcase looks as follows (`test.go`): ``` package main import ( "html/template" "io/ioutil" "net/http" "strconv" ) var funcMap = template.FuncMap{ "humanSize": humanSize, } var tmplGet = template.Must(template.ParseFiles("tmpl.html")).Funcs(funcMap) func humanSize(s int64) string { return strconv.FormatInt(s/int64(1000), 10) + " KB" } func getPageHandler(w http.ResponseWriter, r *http.Request) { files, _ := ioutil.ReadDir(".") if err := tmplGet.Execute(w, files); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } func main() { http.HandleFunc("/", getPageHandler) http.ListenAndServe(":8080", nil) } ``` And I have the following simple template (`tmpl.html`): ``` <html><body> {{range .}} <div> <span>{{.Name}}</span> <span>{{humanSize .Size}}</span> </div> {{end}} </body></html> ``` This is go 1.1.1.

Original source