text/template 包基本用法


text/template 包实现了数据驱动的文本模板生成。

基本模板

package main

import (
	"bytes"
	"fmt"
	"text/template"
)

func main() {
	// 定义模板
	tmpl := `Hello, {{.Name}}! You are {{.Age}} years old.`

	// 解析模板
	t := template.Must(template.New("greeting").Parse(tmpl))

	// 准备数据
	data := struct {
		Name string
		Age  int
	}{
		Name: "张三",
		Age:  25,
	}

	// 执行模板
	var buf bytes.Buffer
	if err := t.Execute(&buf, data); err != nil {
		panic(err)
	}

	fmt.Println(buf.String())
}

条件判断

package main

import (
	"bytes"
	"fmt"
	"text/template"
)

func main() {
	tmpl := `
{{if .IsAdmin}}
欢迎管理员 {{.Name}}{{else}}
欢迎用户 {{.Name}}{{end}}
`

	t := template.Must(template.New("conditional").Parse(tmpl))

	admin := struct {
		Name    string
		IsAdmin bool
	}{"张三", true}

	user := struct {
		Name    string
		IsAdmin bool
	}{"李四", false}

	var buf bytes.Buffer

	t.Execute(&buf, admin)
	fmt.Println(buf.String())

	buf.Reset()
	t.Execute(&buf, user)
	fmt.Println(buf.String())
}

循环

package main

import (
	"bytes"
	"fmt"
	"text/template"
)

func main() {
	tmpl := `购物清单:
{{range .Items}}- {{.Name}}: ¥{{.Price}}
{{end}}
总计: ¥{{.Total}}
`

	type Item struct {
		Name  string
		Price float64
	}

	data := struct {
		Items []Item
		Total float64
	}{
		Items: []Item{
			{"苹果", 5.5},
			{"香蕉", 3.0},
			{"橙子", 4.5},
		},
		Total: 13.0,
	}

	t := template.Must(template.New("list").Parse(tmpl))

	var buf bytes.Buffer
	t.Execute(&buf, data)
	fmt.Println(buf.String())
}

使用函数

package main

import (
	"bytes"
	"fmt"
	"strings"
	"text/template"
)

func main() {
	// 定义自定义函数
	funcMap := template.FuncMap{
		"upper": strings.ToUpper,
		"lower": strings.ToLower,
		"add": func(a, b int) int {
			return a + b
		},
	}

	tmpl := `
大写: {{.Name | upper}}
小写: {{.Name | lower}}
求和: {{add .A .B}}
`

	t := template.Must(
		template.New("funcs").Funcs(funcMap).Parse(tmpl),
	)

	data := struct {
		Name string
		A, B int
	}{"Hello World", 10, 20}

	var buf bytes.Buffer
	t.Execute(&buf, data)
	fmt.Println(buf.String())
}

嵌套模板

package main

import (
	"bytes"
	"fmt"
	"text/template"
)

func main() {
	tmpl := `
{{define "header"}}=== {{.Title}} ==={{end}}
{{define "footer"}}=== 结束 ==={{end}}

{{template "header" .}}
内容: {{.Content}}
{{template "footer"}}
`

	t := template.Must(template.New("nested").Parse(tmpl))

	data := struct {
		Title   string
		Content string
	}{
		Title:   "标题",
		Content: "这是内容",
	}

	var buf bytes.Buffer
	t.Execute(&buf, data)
	fmt.Println(buf.String())
}

从文件加载模板

package main

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

func main() {
	// 从文件加载模板
	t, err := template.ParseFiles("template.html")
	if err != nil {
		panic(err)
	}

	data := struct {
		Title string
		Items []string
	}{
		Title: "我的列表",
		Items: []string{"项目1", "项目2", "项目3"},
	}

	// 输出到标准输出
	t.Execute(os.Stdout, data)
}

实际应用:生成配置文件

package main

import (
	"bytes"
	"fmt"
	"os"
	"text/template"
)

const nginxConf = `
server {
    listen {{.Port}};
    server_name {{.ServerName}};

    location / {
        proxy_pass http://{{.BackendHost}}:{{.BackendPort}};
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    {{range .StaticPaths}}
    location {{.Path}} {
        alias {{.Alias}};
        expires {{.Expires}};
    }
    {{end}}
}
`

type StaticPath struct {
	Path    string
	Alias   string
	Expires string
}

type NginxConfig struct {
	Port         int
	ServerName   string
	BackendHost  string
	BackendPort  int
	StaticPaths  []StaticPath
}

func main() {
	config := NginxConfig{
		Port:        80,
		ServerName:  "example.com",
		BackendHost: "localhost",
		BackendPort: 8080,
		StaticPaths: []StaticPath{
			{"/static/", "/var/www/static", "30d"},
			{"/images/", "/var/www/images", "7d"},
		},
	}

	t := template.Must(template.New("nginx").Parse(nginxConf))

	var buf bytes.Buffer
	if err := t.Execute(&buf, config); err != nil {
		panic(err)
	}

	fmt.Println(buf.String())
}

总结

语法 说明
{{.Field}} 输出字段值
{{if .Cond}}...{{end}} 条件判断
{{range .Slice}}...{{end}} 循环遍历
{{template "name"}} 调用子模板
`{{. func}}`
{{func arg1 arg2}} 调用自定义函数
如有疑问关注公众号给我留言
wx

关注公众号

©2017-2023 鲁ICP备17023316号-1 Powered by Hugo