Go 模板

发布时间: 更新时间: 总字数:1223 阅读时间:3m 作者: IP上海 分享 网址

Go的text/templatehtml/template包用于处理使用字符串模板和数据驱动生成目标字符串,并可以在字符串模板中使用显示数据、流程控制、函数、管道、子模板等功能。

介绍

Template 结构体

  • New 创建目标
  • Parse 解析模板字符串
  • ParseFiles 解析文件模板
  • ParseGlob 解析Glob文件模板
  • Must 对模板创建结果验证
  • Execute 渲染模板
  • ExecuteTemplate 指定渲染模板
  • Funcs 自定义函数
  • Clone 复制模板进行模板复用

预定义函数

参考

  • 逻辑运算:andornot
  • 比较运算:eqneltlegtge
  • 组合模板函数:definetemplateblock
  • 调用操作:call
  • 数组:indexlen
  • 格式化操作:printprintfprintln ,与用直接调用 fmt.Sprint/Sprintf/Sprintln 功能一致
  • 转义:htmljsurlquery 函数对字符串进行转义,防止安全问题

示例

数据显示

package main

import (
	"fmt"
	ht "html/template"
	"os"
	tt "text/template"
)

func main() {
	// 显示数据
	tplText := `hello golang {{ . }}`
	ttpl, err := tt.New("ttpl").Parse(tplText)
	if err != nil {
		fmt.Println(err)
	} else { // hello golang <a href="https://www.xiexianbin.cn">blog</a>
		ttpl.Execute(os.Stdout, `<a href="https://www.xiexianbin.cn">blog</a>`)
		fmt.Println()
	}

	htpl, err := ht.New("htpl").Parse(tplText)
	if err != nil {
		fmt.Println(err)
	} else { // hello golang &lt;a href=&#34;https://www.xiexianbin.cn&#34;&gt;blog&lt;/a&gt;<nil>
		fmt.Println(htpl.Execute(os.Stdout, `<a href="https://www.xiexianbin.cn">blog</a>`))
		fmt.Println()
	}
}
package main

import (
	"fmt"
	"html/template"
	"os"
)

func main() {
	//tplText := `hello golang {{ . }`// 错误演示
	tplText := `hello golang {{ . }}`
	tpl := template.Must(template.New("tpl").Parse(tplText)) // 直接输出错误
	tpl.Execute(os.Stdout, `html/template`)
	fmt.Println()

	// slice
	tplText = `hello golang {{ index . 0 }}`
	tpl = template.Must(template.New("tpl").Parse(tplText))
	tpl.Execute(os.Stdout, []string{"html/template", "golang"})
	fmt.Println()

	// map
	tplText = `hello golang {{ .htmltemplate }} {{ .key1 }}`
	tpl = template.Must(template.New("tpl").Parse(tplText))
	tpl.Execute(os.Stdout, map[string]string{"htmltemplate": "html/template", "key1": "val1"})
	fmt.Println()

	// struct
	tplText = `hello golang {{ .Name }} {{ .Age }}`
	tpl = template.Must(template.New("tpl").Parse(tplText))
	tpl.Execute(os.Stdout, struct {
		Name string
		Age  int
	}{
		Name: "xianbin",
		Age:  18,
	})
}

条件语句

package main

import (
	"html/template"
	"os"
)

func main() {

	// struct 条件语句
	tplText := `hello golang {{ .Name }} {{ .Age }} {{ if eq .Sex 1 }}男{{ else }}女{{ end }}`
	tpl := template.Must(template.New("tpl").Parse(tplText))
	tpl.Execute(os.Stdout, struct {
		Name string
		Age  int
		Sex  int
	}{
		Name: "xianbin",
		Age:  18,
		Sex:  1,
	})

}

遍历

package main

import (
	"html/template"
	"os"
)

func main() {
	tplText := `hello golang {{ range . }} {{ .Name }} {{ .Age }} {{ end }}`
	tpl := template.Must(template.New("tpl").Parse(tplText))
	tpl.Execute(os.Stdout, []struct {
		Name string
		Age  int
	}{{
		Name: "xianbin",
		Age:  18,
	}, {
		Name: "x",
		Age:  19,
	}})
}

自定义函数

  • template.FuncMap()
    • key 字符串,函数名,需要在模板中调用
    • value 函数
package main

import (
	"html/template"
	"os"
	"strings"
)

func main() {
	tplText := `hello golang {{ upper . }} {{ title . }}`
	funcs := template.FuncMap{
		"upper": strings.ToUpper,
		"title": func(str string) string {
			if len(str) == 0 {
				return ""
			} else if len(str) == 1 {
				return strings.ToUpper(str)
			}
			return strings.ToUpper(str[:1]) + str[1:]
		},
	}
	// 模板函数必须在解析模板前加载
	tpl := template.Must(template.New("tpl").Funcs(funcs).Parse(tplText))
	tpl.Execute(os.Stdout, "abcde")
}

模板替代

package main

import (
	"fmt"
	"html/template"
	"os"
)

func main() {
	tplText := `hello golang {{ block "content" . }} {{ . }} {{ end }}`
	tpl := template.Must(template.New("tpl").Parse(tplText))
	tpl.Execute(os.Stdout, "abcde")
	fmt.Println()

	// 替代block
	tpl2 := template.Must(template.New("tpl2").Parse(tplText))
	tpl2, err := tpl2.Parse(`{{ define "content" }}len {{ len . }} {{ end }}`)
	fmt.Println(err, tpl2.Name())
	tpl2.Execute(os.Stdout, "abcde")
	fmt.Println()
}

模板嵌入

package main

import (
	"fmt"
	"html/template"
	"os"
)

func main() {
	tplText := `{{- define "len" }} {{ len . }} {{ end }}
{{- define "raw" }} {{ . }} {{ end }}
{{ template "len" . }}
{{ template "raw" . }}`
	tpl := template.Must(template.New("tpl").Parse(tplText))
	tpl.Execute(os.Stdout, "abcde")
	fmt.Println()

	// 调用指定的方法,替代模板中的 template 指定的模板
	tpl.ExecuteTemplate(os.Stdout, "raw", "abcde")
	fmt.Println()

	// Output:
	// 5
	// abcde
	// abcde
}

ParseFiles 示例

  • 模板文件
$ cat 1.html
{{ range . }}
{{ . }}
{{ end }}

{{ template "2.html" . }}
$ cat 2.html
{{ len . }}
package main

import (
	"html/template"
	"os"
)

func main() {
	tpl := template.Must(template.ParseFiles("1.html", "2.html"))
	tpl.ExecuteTemplate(os.Stdout, "1.html", []string{"a", "b"})
	tpl.ExecuteTemplate(os.Stdout, "2.html", "abcd")
}

ParseGlob 示例

package main

import (
	"html/template"
	"os"
)

func main() {
	tpl := template.Must(template.ParseGlob("*.html"))
	tpl.ExecuteTemplate(os.Stdout, "1.html", []string{"a", "b"})
	tpl.ExecuteTemplate(os.Stdout, "2.html", "abcd")
}

html 模型示例

$ cat views/list.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>users</title>
</head>
<body>
{{ range . }}
{{ .Name }} - {{ .GetName }} <br>
{{ end }}
</body>
</html>
$ cat add.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form name="add" method="post" action="/city/add/">
名称:<input name="name" type="text" /><br>
  <input type="submit" value="Submit">
</form>
</body>
</html>
package main

import (
	"log"
	"net/http"
	"text/template"
)

type City struct {
	Name string
	//NameText func() string // 定义函数,可以使用 call 调用
}

func (c City) GetName() (string, error) {
	return c.Name, nil
}

var cities = []*City{
	&City{
		Name: "shanghai",
	},
	&City{
		Name: "zhengzhou",
	},
	&City{
		Name: "shangqiu",
	},
}

func GetCity() []*City {
	return cities
}

func AddCity(name string) {
	cities = append(cities, &City{
		Name: name,
	})
}

func main() {
	addr := ":8080"
	http.HandleFunc("/city/", func(w http.ResponseWriter, req *http.Request) {
		tpl := template.Must(template.ParseFiles("views/list.html"))
		tpl.ExecuteTemplate(w, "list.html", GetCity())
	})
	http.HandleFunc("/city/add/", func(w http.ResponseWriter, request *http.Request) {
		if request.Method == http.MethodGet {
			tpl := template.Must(template.ParseFiles("views/add.html"))
			tpl.Execute(w, nil)
		} else if request.Method == http.MethodPost {
			log.Println(request.ParseForm())
			name := request.FormValue("name")
			log.Println("name is", name)
			AddCity(name)

			http.Redirect(w, request, "/city/", 302)
		}
		return
	})

	log.Println("listen on", addr)
	log.Fatal(http.ListenAndServe(addr, nil))
}
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数