Go 语言Web开发-模板(template)快速入门教程

模板基础

Go语言模板包是用于生成文本输出的工具,它通过解析模板文本并结合数据生成最终的输出文本。模板语法简洁而强大,包括模板标记、变量输出、控制结构和模板函数等。模板对象表示已解析和编译的模板,可以执行并输出最终文本。模板包的工作原理主要包括模板解析、数据传递和模板执行三个步骤。

text/templatehtml/template 是 Go 语言模板包的两个子包,用于生成文本输出和 HTML 输出。

  • text/template 用于生成任意文本格式的模板,不会自动对输出内容进行 HTML 转义。
  • html/template 专门用于生成 HTML 文档的模板,会自动对输出内容进行 HTML 转义,防止 XSS 攻击。

在浏览器中展示 text/template 的输出时,浏览器也会进行 HTML 转义。这是因为浏览器默认会将接收到的文本内容视为 HTML,从而进行相应的转义处理。因此,无论是 text/template 还是 html/template 生成的内容,在浏览器中显示时都会经过 HTML 转义。所以一般推荐使用

text/template

模板使用

  1. 导入模板库
go 复制代码
import "text/template"
  1. 定义模板
go 复制代码
const textTemplate = "Hello, {{.Name}}! Today is {{.Day}}."

或准备模板文件index.tmpl

Hello, {{.Name}}! Today is {{.Day}}.
  1. 解析模板

解析定义的模板

go 复制代码
tmpl, err := template.New("text_template").Parse(textTemplate)
if err != nil {
    panic(err)
}

或者解析本地准备好的模板文件index.tmpl

go 复制代码
tmpl, err := template.ParseFiles("index.tmpl")
if err != nil {
    panic(err)
}
  1. 准备数据
go 复制代码
data := struct {
    Name string
    Day  string
}{
    Name: "Alice",
    Day:  "Monday",
}
  1. 执行模板
go 复制代码
err = tmpl.Execute(os.Stdout, data)
if err != nil {
    panic(err)
}

完成代码示例

go 复制代码
package main

import (
	"os"
	"text/template"
)

func main() {
	tmpl, _ := template.ParseFiles("index.tmpl")
	data := struct {
		Name string
		Day  string
	}{"Alice", "Monday"}
	tmpl.Execute(os.Stdout, data)	// 输出至控制台
}
// Hello, Alice! Today is Monday.

这里需要注意的是模板文件的扩展名可以自定义,一般是.html.tmpl等。

函数说明

go 复制代码
// 创建一个名为name的模板
func New(name string) *Template

// ParseFiles函数创建一个模板并解析filenames指定的文件里的模板定义【推荐使用】
func ParseFiles(filenames ...string) (*Template, error)

// Must函数用于包装返回(*Template, error)的函数/方法调用,它会在err非nil时panic,一般用于变量初始化
func Must(t *Template, err error) *Template

// ParseGlob创建一个模板并解析匹配pattern的文件(参见glob规则)里的模板定义
func ParseGlob(pattern string) (*Template, error)

// Parse方法将字符串text解析为模板
func (t *Template) Parse(text string) (*Template, error)

// ParseFiles方法解析匹配pattern的文件里的模板定义并将解析结果与t关联
func (t *Template) ParseFiles(filenames ...string) (*Template, error)

// ParseGlob方法解析filenames指定的文件里的模板定义并将解析结果与t关联
func (t *Template) ParseGlob(pattern string) (*Template, error)

// Execute方法将解析好的模板应用到data上,并将输出写入wr
func (t *Template) Execute(wr io.Writer, data interface{}) (err error)

模板语法

模板语法也叫Action,在 Go 的模板包中非常灵活,它包括了标记、变量输出、控制结构和模板函数等功能。模板语法中的标记使用双花括号 {``{ }} 包裹,例如 {``{.FieldName}} 表示输出数据结构中的某个字段。

注释

{{/* a comment */}}
注释,执行时会忽略。可以多行。注释不能嵌套,并且必须紧贴分界符始止。

管道

管道(pipeline)是指产生数据的操作。比如{``{.}}{``{.Name}}等。Go的模板语法中支持使用管道符号|链接多个命令,用法和unix下的管道类似:|前面的命令会将运算结果(或返回值)传递给后一个命令的最后一个位置。

注意 : 并不是只有使用了|才是pipeline。Go的模板语法中,pipeline的概念是传递数据,只要能产生数据的,都是pipeline。

变量

{{ $variable := pipeline }}

Action里可以初始化一个变量来捕获管道的执行结果,变量名以$开头。

条件判断

go 复制代码
{{if pipeline}} T1 {{end}}

{{if pipeline}} T1 {{else}} T0 {{end}}

{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}

这里的pipeline均为布尔表达式。

循环

go 复制代码
{{range pipeline}} T1 {{end}}
如果pipeline的值其长度为0,不会有任何输出

{{range pipeline}} T1 {{else}} T0 {{end}}
如果pipeline的值其长度为0,则会执行T0。

with局部域

go 复制代码
{{with pipeline}} T1 {{end}}
如果pipeline为empty不产生输出,否则将dot设为pipeline的值并执行T1。不修改外面的dot。

{{with pipeline}} T1 {{else}} T0 {{end}}
如果pipeline为empty,不改变dot并执行T0,否则dot设为pipeline的值并执行T1。

模板函数

常见模板函数

and
    函数返回它的第一个empty参数或者最后一个参数;
    就是说"and x y"等价于"if x then y else x";所有参数都会执行;
or
    返回第一个非empty参数或者最后一个参数;
    亦即"or x y"等价于"if x then x else y";所有参数都会执行;
not
    返回它的单个参数的布尔值的否定
len
    返回它的参数的整数类型长度
index
    执行结果为第一个参数以剩下的参数为索引/键指向的值;
    如"index x 1 2 3"返回x[1][2][3]的值;每个被索引的主体必须是数组、切片或者字典。
print
    即fmt.Sprint
printf
    即fmt.Sprintf
println
    即fmt.Sprintln
html
    返回其参数文本表示的HTML逸码等价表示。
urlquery
    返回其参数文本表示的可嵌入URL查询的逸码等价表示。
js
    返回其参数文本表示的JavaScript逸码等价表示。
call
    执行结果是调用第一个参数的返回值,该参数必须是函数类型,其余参数作为调用该函数的参数;
    如"call .X.Y 1 2"等价于go语言里的dot.X.Y(1, 2);
    其中Y是函数类型的字段或者字典的值,或者其他类似情况;
    call的第一个参数的执行结果必须是函数类型的值(和预定义函数如print明显不同);
    该函数类型值必须有1到2个返回值,如果有2个则后一个必须是error接口类型;
    如果有2个返回值的方法返回的error非nil,模板执行会中断并返回给调用模板执行者该错误;

比较函数

eq      如果arg1 == arg2则返回真
ne      如果arg1 != arg2则返回真
lt      如果arg1 < arg2则返回真
le      如果arg1 <= arg2则返回真
gt      如果arg1 > arg2则返回真
ge      如果arg1 >= arg2则返回真

自定义函数

func (t *Template) Funcs(funcMap FuncMap) *Template

Funcs方法向模板t的函数字典里加入参数funcMap内的键值对。如果funcMap某个键值对的值不是函数类型或者返回值不符合要求会panic。但是,可以对t函数列表的成员进行重写。方法返回t以便进行链式调用。

模板嵌套

通过 {``{ define "blockName" }} ... {``{ end }} 定义模板块,并在其他模板中使用 {``{ template "blockName" }} 来引用模板块,实现模板的继承和组合。

index.tmpl

{{template "navbar" .}}

{{template "content" .}}

{{template "footer" .}}

navbar.tmpl

{{define "navbar"}}
<nav>
    Navbar
</nav>
{{end}}

content.tmpl

{{define "content"}}
<div>
    content
</div>
{{end}}

footer.tmpl

{{define "footer"}}
<footer>
    footer
</footer>
{{end}}

一次性导入上述模板文件

go 复制代码
tmpl := template.Must(template.ParseFiles("index.tmpl", "navbar.tmpl", "content.tmpl","footer.tmpl"))

如果模板文件里有引用其他本地静态资源文件得先开启文件服务器

go 复制代码
http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets"))))

如模板文件里引用了assets文件夹里的资源,则需要对其开启文件服务器

go 复制代码
<link rel="stylesheet" href="./assets/css/style.css">
<script src="./assets/src/main.js"></script>
相关推荐
家里有只小肥猫几秒前
el-tree 父节点隐藏
前端·javascript·vue.js
fkalis1 分钟前
【海外SRC漏洞挖掘】谷歌语法发现XSS+Waf Bypass
前端·xss
何曾参静谧4 分钟前
「QT」文件类 之 QTextStream 文本流类
开发语言·qt
monkey_meng8 分钟前
【Rust类型驱动开发 Type Driven Development】
开发语言·后端·rust
落落落sss16 分钟前
MQ集群
java·服务器·开发语言·后端·elasticsearch·adb·ruby
2401_8532757336 分钟前
ArrayList 源码分析
java·开发语言
zyx没烦恼37 分钟前
【STL】set,multiset,map,multimap的介绍以及使用
开发语言·c++
lb363636363637 分钟前
整数储存形式(c基础)
c语言·开发语言
feifeikon39 分钟前
Python Day5 进阶语法(列表表达式/三元/断言/with-as/异常捕获/字符串方法/lambda函数
开发语言·python
大鲤余1 小时前
Rust,删除cargo安装的可执行文件
开发语言·后端·rust