【问题标题】:Template and custom function; panic: function not defined模板和自定义功能;恐慌:功能未定义
【发布时间】:2018-01-19 15:36:36
【问题描述】:

使用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>

这是 1.1.1。

【问题讨论】:

    标签: go


    【解决方案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)
    }
    

    【讨论】:

    • 谢谢。在解析模板之前需要添加函数映射并不明显;我在文档中找不到。我最终得到了var tmplGet = template.Must(template.New("base.html").Funcs(funcMap).ParseFiles("tmpl/base.html", "tmpl/get.html")),因为我使用了嵌套模板。这里的另一个问题是New() 需要与“顶级”模板具有相同的基本名称。
    【解决方案2】:

    解决方案是在 @user321277 建议的函数 New() 和 Parse‌​Files() 中使用相同的名称

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-14
      • 2018-10-19
      • 2020-01-13
      • 1970-01-01
      • 2016-08-27
      • 1970-01-01
      相关资源
      最近更新 更多