Go包text/template语法解析

包模板实现了用于生成文本输出的数据驱动模板。

模板内的数据会用{{}}包裹,{{ action }}其中的内容称为action.

action主要分为俩类内容:

  • 数据的值
  • 控制语句

{{ . }} .代表传入的数据 {{ .title }} 使用传入的title变量

语法介绍

{{/* comment */}} 注释

{{- content -}} 去掉俩边的空格

{{ pipeline }} 输出普通文本

{{ if pipeline }} xxx {{ else if pipeline }} xxx {{ end }} if条件语句

{{ range pipeline }} xxx {{ end }} 简单的循环语句

{{ range pipeline }} xxx {{ else }} xxx {{ end }} 条件循环语句

{{ range $index, $value := pipeline }} xxx {{ end }} 普通的循环语句

{{ define "name" }} 模板 {{ end }} 给模板命名

{{ template "name" }} 引用模板,配合define使用,可以完成模板部分的复用吧

{{ template "name" pipeline }} 条件引用模板

{{ block "name" pipeline }} 自定义模板内容 {{ end }} 使用模板name, 如果没有就使用自定义的模板内容

{{ with pipeline }} 模板1 {{ else }} 模板2 {{ end }} 一个新的上下文,如果条件不为空就模板1,否则模板2

比较运算符

eq 返回 arg1 == arg2 的布尔值

ne 返回 arg1 != arg2 的布尔值

lt 返回 arg1 < arg2 的布尔值

le 返回 arg1 <= arg2 的布尔值

gt 返回 arg1 > arg2 的布尔值

ge 返回 arg1 >= arg2 的布尔值

变量

定义变量: {{ $var = pipeline }}

变量的作用域:模板开始定义的变量作用域在整个模板,模板中块内定义的变量作用域在块内

函数

自定义函数接口:func (t *Template) Funcs(funcMap FuncMap) *Template

全局内置函数

and

{{ and .x .y .z }} xyz全部为true,返回最后一个值(z),如果任意一个为fasle,则返回它

or

{{ or .x .y .z }} xyz任意一个值为true则返回它,全为false则返回最后一个值

call

{{ call .fn .y .z } 调用fn函数传入yz参数,如果结果error不为nil, 则fatal

html 返回转义后的 HTML 字符串,这个函数不能在 html/template 中使用。

js 返回转义后的 JavaScript 字符串。

index 在第一个参数是 array、slice、map 时使用,返回对应下标的值。

index x 1 2 3 等于 x[1][2][3]。

len 返回复合类型的长度。

not 返回布尔类型参数的相反值。

print 等于 fmt.Sprint。

printf 等于 fmt.Sprintf。

println 等于 fmt.Sprintln。

urlquery 对字符串进行 url Query 转义,不能在 html/template 包中使用。

模板解析和执行

解析

引入模板,不存在就报错
func Must(t *Template, err error) *Template
从字符串new模板
func New(name string) *Template
从文件系统中查找符合匹配规则的模板
func ParseFS(fsys fs.FS, patterns ...string) (*Template, error)
加载指定的多个模板文件
func ParseFiles(filenames ...string) (*Template, error)
加载符合匹配条件的模板
func ParseGlob(pattern string) (*Template, error)

执行

//传入模板参数,执行模板,打印输出
err := tmpl.Execute(os.Stdout, "no data needed")
if err != nil {
	log.Fatalf("execution failed: %s", err)
}

//当有加载了很多模板的时候,可以指定要执行的模板名称(T2),传入参数,执行模板,打印输出
err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed")
if err != nil {
	log.Fatalf("execution failed: %s", err)
}

加载匹配的所有的模板

//go:embed tpl/*
templateDir embed.FS
var patternTmpl = []string{
	"tpl/migrate/*.tpl",
	"tpl/*.tpl",
}
tmpl := template.Must(template.ParseFS(templateDir,patternTmpl...))
name := "create,tpl"
data := "User"
if err := tmpl.ExecuteTemplate(b, name, data); err != nil {
	log.Printf("execute template %q: %w", tmpl.Name, err)
}

在模板内使用自定义函数 funcMap

package main

import (
	"log"
	"os"
	"strings"
	"text/template"
)

func main() {
	// First we create a FuncMap with which to register the function.
	funcMap := template.FuncMap{
		// The name "title" is what the function will be called in the template text.
		"title": strings.Title,
	}

	// A simple template definition to test our function.
	// We print the input text several ways:
	// - the original
	// - title-cased
	// - title-cased and then printed with %q
	// - printed with %q and then title-cased.
	const templateText = `
Input: {{printf "%q" .}}
Output 0: {{title .}}
Output 1: {{title . | printf "%q"}}
Output 2: {{printf "%q" . | title}}
`

	// Create a template, add the function map, and parse the text.
	tmpl, err := template.New("titleTest").Funcs(funcMap).Parse(templateText)
	if err != nil {
		log.Fatalf("parsing: %s", err)
	}

	// Run the template to verify the output.
	err = tmpl.Execute(os.Stdout, "the go programming language")
	if err != nil {
		log.Fatalf("execution: %s", err)
	}

}

参考资料