一、基础概念
Go 标准库 html/template 是 Go 内置的网页模板引擎,用于后端把数据填充到 HTML 页面,再返回给浏览器。
所有模板语法都包裹在 {``{ }} 两个大括号之中,大括号必须紧贴,不要随意加多余空格。
1.1 核心符号:点 .
{``{ . }}:.(点)代表当前作用域的对象 / 数据 ,也就是t.Execute(w, 数据)第二个参数传入的值。- 如果传入的是结构体对象,想要获取结构体字段:
{``{ .字段名 }}{``{ .Name }}获取 Name 字段{``{ .Age }}获取 Age 字段
⚠️ 重要坑点:Go 结构体只有首字母大写的字段才能被模板访问。小写字段是私有字段,模板无法读取!
go
运行
Gotype User struct { Name string // 大写,模板可读 gender string // ×小写私有,模板读取不到! Age int // 大写,模板可读 }
二、完整基础示例(Web 服务渲染模板)
2.1 项目文件结构
plaintext
├─ main.go // Go后端代码
└─ hello.tmpl // 网页模板文件(html)
2.2 模板文件 hello.tmpl
html
预览
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
<p>Hello {{ . }}</p>
</body>
</html>
2.3 Go 后端代码 main.go
go
运行
Go
package main
import (
"fmt"
"html/template"
"net/http"
)
// User 定义结构体
type User struct {
Name string
Gender string
Age int
}
// sayHello 请求处理函数
// w: 用于给浏览器返回响应;r: 获取浏览器发来的请求信息
func sayHello(w http.ResponseWriter, r *http.Request) {
// ----------------------1.解析模板----------------------
t, err := template.ParseFiles("./hello.tmpl")
if err != nil {
fmt.Printf("parse template failed,err:%v", err)
return
}
// ----------------------2.准备渲染数据----------------------
u1 := User{
Name: "小王子",
Gender: "男",
Age: 18,
}
// ----------------------3.渲染模板,把数据填充进模板返回浏览器----------------------
t.Execute(w, u1)
}
func main() {
// 注册路由:访问根路径 / 执行sayHello函数
http.HandleFunc("/", sayHello)
// 启动web服务器,端口9000
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Printf("HTTP server start failed, err:%v", err)
return
}
}
启动程序后,浏览器访问 http://127.0.0.1:9000 即可查看渲染结果。
2.4 两种常用传参方式
方式 1:传入结构体
go
运行
Go
u1 := User{Name:"小王子",Gender:"男",Age:18}
t.Execute(w,u1)
模板取值:{``{ .Name }}、{``{ .Age }}
方式 2:传入 map
go
运行
Go
m1 := map[string]interface{}{
"name":"小王子",
"gender":"男",
"age":18,
}
t.Execute(w,m1)
模板取值:{``{ .name }}、{``{ .age }}
三、模板基础语法大全
3.1 模板注释
go
运行
Go
{{/*遇事不决写注释*/}}
- 注释内容执行渲染时会被忽略,不会输出到网页
- 支持多行注释
- ❗不能嵌套注释,分界符不能加空格
3.2 Pipeline(管道数据流)
pipeline 就是能够产生数据的操作。 模板中所有可以传递、产生数据的表达式,都属于 pipeline,数据顺着管道向后传递。
3.3 模板内部变量定义
go
运行
Go
{{$v1 := 100}}
{{$age := 19}}
- 变量必须带
$符号 - 定义之后可以在模板任意位置使用:
{``{ $v1 }}
3.4 移除多余空格 {``{- -}}
- 符号用来消除渲染后生成 HTML 的换行和空格
go
运行
Go
{{- .Name -}}
{``{-:删除左边空格换行-}}:删除右边空格换行
四、条件判断 if‑else
基础语法
go
运行
Go
{{ if $v1 }}
{{ $v1 }}
{{else}}
啥都没有
{{end}}
if 判断必须以
{``{end}}结尾闭合!
内置比较函数
表格
| 函数 | 含义 |
|---|---|
| lt | less‑than 小于 |
| le | 小于等于 |
| eq | 等于 |
| ne | 不等于 |
| gt | 大于 |
| ge | 大于等于 |
示例:
go
运行
Go
{{ if lt .age 22 }}
好好上学
{{else}}
好好工作
{{end}}
五、循环遍历 range
适合遍历切片、数组、map 数据
后端准备切片数据
go
运行
Go
hobbyList := []string{
"篮球",
"足球",
"双色球",
}
data := map[string]interface{}{
"hobby": hobbyList,
}
t.Execute(w, data)
模板循环写法
go
运行
Go
{{ range $idx, $hobby := .hobby}}
<p>{{$idx}} - {{$hobby}}</p>
{{end}}
$idx:索引下标$hobby:遍历取出的元素值
range + else(空数据兜底)
当切片长度为 0 的时候,会执行 else 分支
go
运行
Go
{{ range $idx, $hobby := .hobby}}
<p>{{$idx}} - {{$hobby}}</p>
{{else}}
<p>没啥爱好</p>
{{end}}
六、with 作用域简写
with 可以切换当前. 的指向,简化很长的变量路径,创造局部作用域。
不使用 with(完整写法)
go
运行
Go
<p>{{ .m1.name }}</p>
<p>{{ .m1.age }}</p>
使用 with 简写
go
运行
html
{{with .m1}}
<p>{{ .name }}</p>
<p>{{ .age }}</p>
{{end}}
在 with 块内部,
.就代表.m1,不用每次都写完整路径
七、index 索引取值
用于根据下标获取切片、数组指定位置的元素
go
运行
Go
{{index .hobby 2 }}
代表取切片 .hobby 中下标为 2 的元素
八、速查思维导图
- 包裹标记:
{``{ 内容 }} .= 当前对象- 取字段:
{``{ .Name }} - 注释:
{``{/* 注释 */}} - 变量:
{``{ $x := 值 }} - 去空格:
{``{- .xxx -}} - 判断:
{``{if}} ... {``{else}} ... {``{end}} - 循环:
{``{range}} ... {``{else}} ... {``{end}} - 简写域:
{``{with 目标}} ... {``{end}}10. 索引取值:{``{index 数组 下标}}