Iris offers support for 6 template parsers out of the box
Engine | Declaration | Underline Template Parser |
---|---|---|
std template/html | iris.HTML(...) | html/template package |
django | iris.Django(...) | iris-contrib/pongo2 package |
handlebars | iris.Handlebars(...) | Joker/jade package |
amber | iris.Amber(...) | aymerick/raymond package |
pug(jade) | iris.Pug(...) | eknkc/amber package |
jet | iris.Jet(...) | CloudyKit/jet package |
Go 模板是一种功能强大的定制输出的方法,无论您是在创建网页、发送电子邮件、使用 Buffalo、 Go-hugo 还是仅使用一些 CLI,比如 kubectl。
Control Structure | Definition |
---|---|
{{/* a comment */}} | Defines a comment |
{{.}} | Renders the root element |
{{.Title}} | Renders the “Title”-field in a nested element |
{{if .Done}} {{else}} {{end}} | Defines an if-Statement |
{{range .Todos}} {{.}} {{end}} | Loops over all “Todos” and renders each using {{.}} |
{{block "content" .}} {{end}} | Defines a block with the name “content” |
- {{$number := .}}
- <h1> It is day number {{$number}} of the month </h1>
- <h1>Hello, {{if .Name}} {{.Name}} {{else}} there {{end}}!</h1>
我们可以通过忽略或最小化效果来更改我们的模板以更好地处理它,或者我们可以使用减号输出模板。
- <h1>Hello, {{if .Name}} {{.Name}} {{- else}} Anonymous {{- end}}!</h1>
- type Item struct {
- Name string
- Price int
- }
-
- type ViewData struct {
- Name string
- Items []Item
- }
- {{range .Items}}
- <div>
- <h3>{{.Name}}</h3>
- <span>${{.Price}}</span>
- </div>
- {{end}}
- <body>
- <h1> {{index .FavNums 2 }}</h1>
- </body>
- type person struct {
- Name string
- FavNums []int
- }
-
- func main() {
- tpl := template.Must(template.ParseGlob("*.gohtml"))
- tpl.Execute(os.Stdout, &person{"Curtis", []int{7, 11, 94}})
- }
- {{if and .User .User.Admin}}
- You are an admin user!
- {{else}}
- Access denied!
- {{end}}
- type User struct {
- Admin bool
- }
-
- type ViewData struct {
- *User
- }
eq 函数比较特殊,可以拿多个参数和第一个参数进行比较:
{{ eq arg1 arg2 arg3 arg4}} => arg1==arg2 || arg1==arg3 || arg1==arg4
函数调用可以链式调用,前一个函数的输出结果作为下一个函数调用的参数。html/template称之为管道,类似于linux shell命令中的管道一样,它采用|分隔。
注意前一个命令的输出结果是作为下一个命令的最后一个参数,最终命令的输出结果就是这个管道的结果。
嵌套模板可以用于经常跨模板、页脚或页眉使用的部分代码。 与分别更新每个模板不同,我们可以使用所有其他模板都可以使用的嵌套模板。
- {{define "footer"}}
- <footer>
- <p>Here is the footer</p>
- </footer>
- {{end}}
-
定义了一个名为“ footer”的模板,可以在其他模板中使用,例如:
- {{template "footer"}}
-
用于包含嵌套模板的template操作还允许第二个参数将数据传递给嵌套模板。
- // Define a nested template called header
- {{define "header"}}
- <h1>{{.}}</h1>
- {{end}}
-
- // Call template and pass a name parameter
- {{range .Items}}
- <div>
- {{template "header" .Name}}
- <span>${{.Price}}</span>
- </div>
- {{end}}
-
- // Omitted imports & package
-
- var LayoutDir string = "views/layouts"
- var bootstrap *template.Template
-
- func main() {
- var err error
- bootstrap, err = template.ParseGlob(LayoutDir + "/*.gohtml")
- if err != nil {
- panic(err)
- }
-
- http.HandleFunc("/", handler)
- http.ListenAndServe(":8080", nil)
- }
-
- func handler(w http.ResponseWriter, r *http.Request) {
- bootstrap.ExecuteTemplate(w, "bootstrap", nil)
- }
views/layouts/bootstrap.gohtml 示例文件:
- {{define "bootstrap"}}
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <title>Go Templates</title>
- <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
- </head>
- <body>
- <div>
- <h1>Filler header</h1>
- <p>Filler paragraph</p>
- </div>
- <!-- jquery & Bootstrap JS -->
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
- <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
- </body>
- </html>
- {{end}}
- type User struct {
- ID int
- Email string
- }
-
- func (u User) HasPermission(feature string) bool {
- if feature == "feature-a" {
- return true
- } else {
- return false
- }
- }
- {{if .User.HasPermission "feature-a"}}
- <div>
- <h3>Feature A</h3>
- <p>Some other stuff here...</p>
- </div>
- {{else}}
- <div>
- <h3>Feature A</h3>
- <p>To enable Feature A please upgrade your plan</p>
- </div>
- {{end}}
如果方法 HasPermission 有时需要更改,则函数变量(方法)实现可能不适合设计。 相反,可以在 User 类型上添加 HasPermission func (string) bool 属性。 这样,在创建时就可以为它分配一个函数:
- // Structs
- type ViewData struct {
- User User
- }
-
- type User struct {
- ID int
- Email string
- HasPermission func(string) bool
- }
-
- // Example of creating a ViewData
- vd := ViewData{
- User: User{
- ID: 1,
- Email: "curtis.vermeeren@gmail.com",
- // Create the HasPermission function
- HasPermission: func(feature string) bool {
- if feature == "feature-b" {
- return true
- }
- return false
- },
- },
- }
-
- // Executing the ViewData with the template
- err := testTemplate.Execute(w, vd)
call 关键字告诉 Go 模板我们想要调用这个函数:
- {{if (call .User.HasPermission "feature-b")}}
- <div>
- <h3>Feature B</h3>
- <p>Some other stuff here...</p>
- </div>
- {{else}}
- <div>
- <h3>Feature B</h3>
- <p>To enable Feature B please upgrade your plan</p>
- </div>
- {{end}}
{{ "hello!" | upper | repeat 5 }}
生成
HELLO!HELLO!HELLO!HELLO!HELLO!
- // Creating a template with function hasPermission
- testTemplate, err = template.New("hello.gohtml").Funcs(template.FuncMap{
- "hasPermission": func(user User, feature string) bool {
- if user.ID == 1 && feature == "feature-a" {
- return true
- }
- return false
- },
- }).ParseFiles("hello.gohtml")
- {{ if hasPermission .User "feature-a" }}
大型应用程序中,向模板传递过多的对象可能会变得难以跨主模板进行维护。 我们可以将自定义函数的实现更改为不使用,例如创建一个默认的 hasPermission 函数:
- testTemplate, err = template.New("hello.gohtml").Funcs(template.FuncMap{
- "hasPermission": func(feature string) bool {
- return false
- },
- }).ParseFiles("hello.gohtml")
这个函数可以放在 main ()或其他地方,以确保在 hello.gohtml 函数映射中创建默认的 hasPermission。 默认函数只返回 false,但它定义了不需要 User 的函数和实现。
接下来可以使用闭包重新定义 hasPermission 函数。 它将使用在处理程序中创建时可用的 User 数据,而不是将 User 数据传递给它。 在模板的处理程序中,您可以重新定义任何函数以使用可用的信息。
- func handler(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "text/html")
-
- user := User{
- ID: 1,
- Email: "Curtis.vermeeren@gmail.com",
- }
- vd := ViewData{}
- err := testTemplate.Funcs(template.FuncMap{
- "hasPermission": func(feature string) bool {
- return user.ID == 1 && feature == "feature-a"
- },
- }).Execute(w, vd)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- }
- }
除了官方的预定义的函数外,一些第三方也定义了一些函数,你可以使用这些库,避免重复造轮子。