开发者

Go库text与template包使用示例详解

开发者 https://www.devze.com 2022-12-16 10:45 出处:网络 作者: 小马别过河
目录场景text/template 包基本用法模板语法空白字符常用 Action函数总结场景 现在的项目,基本都是前后端分离,后端只要提供json等格式的数据就行。在这个背景下,模板渲染这个功能备受冷落,很少会在项目中用到。
目录
  • 场景
  • text/template 包
    • 基本用法
    • 模板语法
      • 空白字符
      • 常用 Action
      • 函数
  • 总结

    场景

    现在的项目,基本都是前后端分离,后端只要提供json等格式的数据就行。在这个背景下,模板渲染这个功能备受冷落,很少会在项目中用到。

    虽然在 http 服务中,模板解析不常用,但日常开发中,巧妙利用模板生成代码,能使我们开发事半功倍。http://www.devze.com比如:

    • 使用模板初始化项目。比如我们每次新建一个 http 服务,可能都需要 promethue 监控、日志等模块。每次都实现一遍不现实,(或者 copy 别的项目),我们可以写好模板,支持自定义项目名,初始化新项目。
    • 生成代码。比如之前文章提到的 mockery,就是解析 interface 的语法树,利用模板生成 Mock 对象。

    text/template 包

    基本用法

    text/template提供的接口和html/template包一样,只不过后者会为 html 格式的输出做转义,避免攻击。

    text/template 用法很简单:

    func main() {
    	// 要注入的变量
    	type Inventory struct {
    		Material string
    		Chttp://www.devze.comount    uint
    	}
    	sweaters := Inventory{"wool", 17}
    	// 模板内容, {{.xxx}} 格式的都会被注入的变量替换
    	text := `{{.Count}} items are made of {{.Material}}`
    	TestTemplate(text, sweaters)
    }
    func TestTemplate(text string, data interface{}) {
    	// 初始化,解析
    	tmpl, err := template.New("test").Parse(text)
    	if err != nil {
    		panic(err)
    	}
    	// 输出到 os.Stdout
    	err = tmpl.Execute(os.Stdout, data)
    	if err != nil {
    		panic(err)
    	}
    }
    

    结果输出如下:

    17 items are made of wool

    其中,Execute的声明为:

    // 第一个参数是输出的接口,第二个参数是要注入的数据
    func (t *Template) Execute(wr io.Writer, data interface{}) error
    

    第二个参数 data 是 interface{},类型不限,可以是:

    • 结构体,属性在模板中用 {{.Field}} 表示。
    • map,value 在模板中用 {{.Key}} 表示。
    • 其他简单类型(int、string等),在模板中用{{.}}表示。
    	// data 为 map
    	m := map[string]interface{}{"Material": "wool", "Count": 17}
    	TestTemplate(`{{.Count}} items are made of {{.Material}}`, m) // 输出:17 items are made of wool
    	// data 为 int,{{.}} 代表注入的变量
    	TestTemplate(`{{.}} items`, 17) // 输出:17 items
    

    另外,我们也可以使用 template.Must 来检测返回的 error, 如果 error 不为 nil 则 panic。也就是说下面的代码:

    tmpl, err := template.New("test").Parse(text)
    if err != nil {
      panic(err)
    }
    

    等价于:

    tmpl := template.Must(template.New("test").Parse(txt))
    

    我们重点介绍一下,Parse的参数(代码中的text变量),也就是模板的内容。

    模板语法

    模板里{{xxx}}http://www.devze.com格式称之为 Action,默认以{{}}作为分界符,表示模板的流程控制、或者变量。

    空白字符

    如果 Action 以 {{- 开头,会把 action 左边的空白字符删除,这里的空白字符包括空格、换行、tab等。同理,-}}会把右边的空白字符删除。如:

    	d := struct{ Name string }{"Neil"}
    	TestTemplate(`name = {{.Name}} ;`, d) // 输出:name = Neil ;
    	// 删除掉 .Name 左边的空格
    	TestTemplate(`name = {{- .Name}} ;`, d) // 输出:name =Neil ;
    	// 删除掉 .Name 右边的空格
    	TestTemplate(`name = {{.Name -}} ;`, d) // 输出:name = Neil;
    	// 删除掉 .Name 两边的空格
    	TestTemplate(`name = {{- .Name -}} ;`, d) // 输出:name =Neil;
    

    常用 Action

    备注,格式为 {{/*xxxx*/}},注意备注的内容是可以换行的。

    text := `{{/*thphpis is a comment*/}} name : {{.}} `
    TestTemplate(text, "Neil")
    // 输出:
    //  name : Neil 
    

    遍历,可以使用 range 关键字。遍历的变量只能是 slice、array、map 或者 channel。

    下面代码中的 {{.}} 代表 .MapContent 的元素。

    d1 := struct{ MapContent []string }{MapContent: []string{"neil", "garmen", "ray"}}
    text = "{{range .MapContent}}{{.}} {{end}}"
    TestTemplate(text, d1)
    // 输出:
    // neil garmen ray
    

    注意,这时候的.不是代表d1变量,如果希望在 range 块里面使用d1, 需要使用 {{$.}}

    另外也可以使用自定义变量来遍历:

    text = "{{range $i,$v := .MapContent}}{{$i}}=>{{$v}} {{end}}"
    TestTemplate(text, d1)
    // 输出
    // 0=>neil 1=>garmen 2=>ray
    

    if-else,变量为零值,或者空 slice、array、map,就相当于是 false。

    text = `{{if .Name}}emtpy{{else}}not empty{{end}}`
    d = struct{ Name string }{"Neil"}
    TestTemplate(text, d) // 输出: empty
    

    if 还可以配合 and、or、not 使用:

    // .condition1 && .condition2 
    if and .condition1 .condition2 
    // .condition1 ||  .condition2 
    if or .condition1 .condition2 
    // !.condition
    if not .condition
    

    with-else, 和if基本一样。区别是,with 作用域的 {{.}} 代表 with 参数,而不是全局的 {{.}}.

    text = "{{with .Name}}{{.}}{{else}}empty{{end}}"
    d = struct{ Name string }{"Neil"}
    TestTemplate(text, d) // 输出: Neil
    

    自定义模板,使用 define开发者_Python培训义,template 引用。

    text = `{{define "T1"}}ONE{{end}}
    {{define "T2"}}TWO{{end}}
    {{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
    {{template "T3"}}`
    TestTemplate(text, nil)
    // 输出: ONE TWO
    

    函数

    模板提供了一些函数,如上文的andornot。比如下文的 index 函数,打印 MapContent 的 index 为 1 的元素。

    text = `{{index .MapContent 1}}`
    d1 = struct{ MapContent []string }{MapContent: []string{"neil", "garmen", "ray"}}
    TestTemplate(text, d1)
    // 输出:garmen
    

    另外,函数还能以管道的方式,一个函数的结果,作为另一个参数的输入,如 {{func1 args | func2 }}。还有可以使用自定义函数,详情可以查看官方文档:pkg.go.dev/text/templa…。

    总结

    text/template 功能挺多,本文只是大致介绍一下,详情还得移步官网

    以上就是Go库tepythonxt与template包使用示例详解的详细内容,更多关于Go库text template包的资料请关注我们其它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号