Подтвердить что ты не робот

Шаблон и пользовательская функция; panic: функция не определена

Использование html/template Я пытаюсь использовать одну из своих собственных функций внутри шаблона. К сожалению, я не могу использовать функцию функциональной карты шаблонов go. Все, что я получаю, это следующая ошибка:

% go run test.go
panic: template: tmpl.html:5: function "humanSize" not defined
[...]

Уменьшенный тестовый файл выглядит следующим образом (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)
}

И у меня есть следующий простой шаблон (tmpl.html):

<html><body>
    {{range .}}
    <div>
        <span>{{.Name}}</span>
        <span>{{humanSize .Size}}</span>
    </div>
    {{end}}
</body></html>

Это go 1.1.1.

4b9b3361

Ответ 1

IIRC, карта шаблонов функций должна быть определена .Funcs перед разбором шаблона. Кажется, что работает код ниже.

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)
}

Ответ 2

Решение состоит в том, чтобы иметь одинаковые имена в функциях New() и Parse Files(), предложенных пользователем @user321277

var tmplGet = template.Must(template.New("base.html").Funcs(funcMap).Parse‌​Files("tmpl/base.htm‌​l", "tmpl/get.html"))