這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
和大多數語言的的模板文法類似:{{.Name | FuncName}}
go本身內建了一些模板函數,我們現在來看一看如何自訂模板函數:
先來看一個函式宣告:
func (t *Template) Funcs(funcMap FuncMap) *Template
Funcs函數就是用來建立我們模板函數的函數了,它需要一個FuncMap類型的參數,繼續看手冊
type FuncMap map[string]interface{}
官方文檔裡是這麼解釋的
FuncMap is the type of the map defining the mapping from names to functions. Each function must have either a single return value, or two return values of which the second has type error. In that case, if the second (error) argument evaluates to non-nil during execution, execution terminates and Execute returns that error.
簡單翻譯一下就是
這是一個map,是名稱與函數的映射,其中key對應的就是你在模板中使用的函數名稱,不一定要和你在原始碼檔案
中定義的函數名同名,需要注意的是這個map的value,它是一個interface{}類型的,但實際上應該給它一個
指定類型的函數名,這個函數是這樣的:
func functionName(args ...interface{}) string
你也可以有第二個傳回值,但必須是error類型的。如果函數執行沒有出錯,那這個值必須是nil,
我們來看一下具體的使用方法:
func Index(w http.ResponseWriter, r *http.Request) { //用於儲存資料的map data := make(map[string]string) //儲存模板函數 tempfunc := make(template.FuncMap) tempfunc["ShowName"] = ShowName t, _ := template.ParseFiles("index.html") //註冊模板函數 t = t.Funcs(tempfunc) data["Name"] = "BCL" t.Execute(w, data)}//這個樣本函數,將傳進來的字串用*****包起來func ShowName(args ...interface{}) string { //這裡只考慮一個參數的情況 var str string = "" if s, ok := args[0].(string); ok { str = "*****" + s + "*****" } else { str = "Nothing" } return str}
如果這麼寫的話,似乎看上去並沒有什麼問題,並且編譯能通過,
開啟瀏覽器訪問,發現似乎除了問題:
[4]
並且出現了以下的錯誤:
2015/07/22 22:38:07 http: panic serving 127.0.0.1:37346: runtime error: invalid memory address or nil pointer dereference
goroutine 5 [running]:
net/http.func·011()
/opt/go/src/net/http/server.go:1130 +0xbb
html/template.(*Template).Funcs(0x0, 0xc20803af30, 0x1)
/opt/go/src/html/template/template.go:276 +0x1f
main.Index(0x7fda0d28a278, 0xc20804cc80, 0xc208032d00)
/home/buchenglei/workspace/golang/src/test/test.go:18 +0x121
net/http.HandlerFunc.ServeHTTP(0x7cee28, 0x7fda0d28a278, 0xc20804cc80, 0xc208032d00)
/opt/go/src/net/http/server.go:1265 +0x41
net/http.(*ServeMux).ServeHTTP(0xc20803aa20, 0x7fda0d28a278, 0xc20804cc80, 0xc208032d00)
/opt/go/src/net/http/server.go:1541 +0x17d
net/http.serverHandler.ServeHTTP(0xc208070060, 0x7fda0d28a278, 0xc20804cc80, 0xc208032d00)
/opt/go/src/net/http/server.go:1703 +0x19a
net/http.(*conn).serve(0xc20804cbe0)
/opt/go/src/net/http/server.go:1204 +0xb57
created by net/http.(*Server).Serve
/opt/go/src/net/http/server.go:1751 +0x35e
需要改寫模板解析的函數
func Index(w http.ResponseWriter, r *http.Request) { //用於儲存資料的map data := make(map[string]string) tempfunc := make(template.FuncMap) tempfunc["showname"] = ShowName //得給模板起個名字才行 t := template.New("index.html") t = t.Funcs(tempfunc) t, _ = t.ParseFiles("./index.html") data["Name"] = "BCL" t.Execute(w, data)}
這樣即可得到正確的輸出結果
注意
如果待輸出到模板中的字串是一個html片段的話,它是會被轉義的,解決辦法就是用template.HTML()將html片段包裹起來,再送到模板中解析,這樣就能保證html代碼被瀏覽器正確執行。