2013-07-24 4 views
18

Mit html/template Ich versuche, eine meiner eigenen Funktionen in einer Vorlage zu verwenden. Leider kann ich die Funktionskartenfunktion von go's Templates nicht verwenden. Alles, was ich die folgende Fehlermeldung erhalten:Vorlage und benutzerdefinierte Funktion; Panik: Funktion nicht definiert

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

Der reduzierte Testfall sieht wie folgt aus (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) 
} 

Und ich habe die folgende einfache Vorlage (tmpl.html):

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

Dies ist 1.1.1.

Antwort

30

IIRC, Template-Funktionen müssen vor dem Analysieren der Vorlage von .Funcs definiert werden. Der folgende Code scheint zu funktionieren.

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

Danke. Es ist nicht offensichtlich, dass Sie vor dem Analysieren der Vorlage die Funktionszuordnung hinzufügen müssen. Ich kann das in der Dokumentation nicht finden. Ich endete mit 'var tmplGet = template.Must (template.New (" base.html "). Funcs (funcMap) .ParseFiles (" tmpl/base.html "," tmpl/get.html "))', weil Ich verwende verschachtelte Vorlagen. Ein weiteres Problem ist, dass 'New()' denselben Basisnamen haben muss wie die Vorlage "Top Level". –

0

Die Lösung ist durch @ gleichen Namen in der Funktion New() und Parse-Dateien() eine vorgeschlagen haben user321277

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