Go 视图模板篇(三):参数、管道和函数调用
参数
参数可以看做模板中的变量,参数值可以是布尔值、整型、字符串、还可以是结构体、结构体的字段、或者数组的索引。
我们可以这样设置参数值:
$variable := value
乍看起来没啥用,用在指令中则可以大放异彩:
{{ range $key, $value := . }}
The key is {{ $key }} and the value is {{ $value }}
{{ end }}
管道
管道是链接起来的参数、函数或者方法序列,和 Unix 管道一样:
{{ p1 | p2 | p3 }}
管道允许我们将上一个输出作为参数传递到下一个,不同元素之间通过 |
分隔。
服务端处理器示例代码:
package main
import (
"html/template"
"net/http"
)
func pipelineExample(w http.ResponseWriter, r *http.Request) {
t := template.Must(template.ParseFiles("pipeline.html"))
t.Execute(w, 12.3456)
}
func main() {
http.HandleFunc("/pipeline", pipelineExample)
http.ListenAndServe(":8080", nil)
}
对应的模板文件 pipeline.html
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Pipeline Demo</title>
</head>
<body>
{{ . | printf "%.2f" }}
</body>
</html>
上述管道代码会将传入视图模板的变量作为 printf
函数的参数,通过 %.2f
格式打印出来:
printf
函数封装了 fmt.Sprintf
方法,是 Go 模板引擎内置的函数,如果是自定义函数的话,需要通过指定语法将其绑定到模板引擎,否则系统不能识别,下面我们就来看看如何在 Go 视图模板中通过管道调用自定义函数。
自定义函数
Go 模板引擎内置了丰富的基础函数,其中有很多是 fmt.Sprint
的变体,比如前面示例中使用的 printf
。此外,还支持开发者自定义的函数。
要自定义函数,需要这么做:
- 创建
FuncMap
字典,然后将函数名作为键,将函数体作为值。 - 将
FuncMap
应用到模板引擎。
下面我们来看一个示例,这个示例中,我们通过自定义函数设置日期输出格式。
编写服务端处理器示例代码如下:
package main
import (
"html/template"
"net/http"
"time"
)
func formatDate(t time.Time) string {
layout := "2006-01-02 15:04:05"
return t.Format(layout)
}
func customFunctionExample(w http.ResponseWriter, r *http.Request) {
funcMap := template.FuncMap{
"fdate": formatDate,
}
t := template.New("function.html").Funcs(funcMap)
t, _ = t.ParseFiles("function.html")
t.Execute(w, time.Now())
}
func main() {
http.HandleFunc("/date_format", customFunctionExample)
http.ListenAndServe(":8080", nil)
}
可以看到,我们通过模板引擎提供的 FuncMap
方法将自定义的 formatDate
函数注册到 fdate
键,然后将返回的 funcMap
通过 Funcs
方法注入到视图模板中,这样,在对应的视图模板中就可以调用 funcMap
中注册的自定义函数了。
对应的模板文件 function.html
代码如下,我们在里面通过管道的方式调用了 fdate
函数:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Custom Function</title>
</head>
<body>
<div> The date/time is {{ . | fdate }} </div>
</body>
</html>
这里需要注意的是,我们必须在解析模板之前应用自定义函数到模板引擎(前后顺序不能颠倒):
t := template.New("function.html").Funcs(funcMap)
t, _ = t.ParseFiles("function.html")
这是因为在解析模板时需要确定模板中使用的函数。另外,当我们通过 New
方法创建模板时,需要手动设置模板名(之前都是自动将文件名作为模板名),然后在模板上调用 ParseFiles
时再次传递的实际上是待解析的模板文件,而不是模板名,这里需要区分下。
运行服务端代码启动服务器,在浏览器中访问 http://localhost:8080/date_format
,输出结果如下,表明自定义日期格式函数调用成功:
除了管道之外,还可以在指令中使用自定义的函数,这个时候可以将 .
作为参数传递过来:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Go Web Programming</title>
</head>
<body>
<div>The date/time is {{ fdate . }}</div>
</body>
</html>
两种方式实现的效果一样,但可以看出,管道的方式更加直观和灵活,我们还可以在后面继续追加其他函数对结果进行处理(链式调用)。
No Comments