必须用Execute或ExecuteTemplate传数据,参数需为map/struct等可访问结构而非字符串;.是当前作用域,$是根数据;ParseFiles路径基于可执行文件目录;简单替换可用strings.Replacer。

text/template 里怎么传变量进去
必须用 Execute 或 ExecuteTemplate 方法,且第二个参数是数据结构(map、struct、基本类型),不能直接传字符串或空接口切片。常见错误是把变量名当字符串硬塞进去,比如写 t.Execute(os.Stdout, "name")——这只会输出字面量 "name",不是取值。
正确做法是传一个能被模板访问的上下文:
- 用
map[string]interface{}:键名就是模板里写的变量名,如map[string]interface{}{"Name": "Alice"},模板中写{{.Name}} - 用 struct:字段必须首字母大写(导出),且建议加
jsontag 方便调试,如type User struct { Name string `json:"name"` } - 传 nil 数据会 panic,哪怕模板没用到字段;传空 struct 也不行,
{{.Name}}会报nil pointer dereference
模板语法里 . 和 $ 的区别在哪
. 是当前作用域的数据,$ 是最外层传入的根数据。嵌套循环或 with 语句里 . 会变,$ 始终不变。容易踩坑的是在 {{range}} 里想访问根级字段却只写 {{.ID}},结果找不到——因为 . 此时是 range 的每个元素。
示例:
立即学习“go语言免费学习笔记(深入)”;
{{range .Users}}
{{.Name}} 来自 {{$.Region}} // 用 $.Region 访问根数据
{{end}}
-
{{.}}在顶层是 map/struct,在{{range}}内是当前迭代项 -
{{$}}合法,但一般只用$;{{$.User.Name}}等价于顶层的{{.User.Name}} - 不推荐在模板里做复杂逻辑,
$不是“全局变量”,只是根数据别名
template.ParseFiles 报错 “no such file or directory” 怎么查
路径是相对 os.Executable() 所在目录,不是当前工作目录(os.Getwd()),也不是 go run 所在路径。绝大多数情况是路径写死了但二进制移动后失效。
- 用
filepath.Join(filepath.Dir(os.Args[0]), "tmpl.html")拼路径,比硬写"./templates/foo.tmpl"可靠 - 检查文件是否被 gitignore 或构建工具排除;
go build不会自动打包 .tmpl 文件 - 开发期可用
template.Must(template.New("").ParseFiles(...))快速暴露解析错误,但上线要换回带 error 检查的写法 - Windows 下注意反斜杠转义问题,统一用
filepath.Join,别手动拼"\"
想替换字符串但不用完整 template 对象,有没有轻量方式
有,用 strings.Replacer。它不解析语法,只做字面量替换,适合简单场景(比如日志模板、URL 路径填充),性能比 text/template 高一个数量级。
示例:
立即学习“go语言免费学习笔记(深入)”;
r := strings.NewReplacer("{name}", "Bob", "{age}", "30")
result := r.Replace("Hello {name}, you are {age} years old")
-
strings.Replacer替换顺序无关,但要注意重叠匹配(如"{a}"和"{ab}"),它按字符串长度降序处理 - 不支持条件、循环、函数调用;无法处理嵌套结构或动态字段名
- 如果模板里有
{{这种字符,Replacer会照常替换,而text/template会报错——这是安全边界,别混用
真正需要变量展开、格式化、嵌套逻辑时,text/template 是唯一靠谱选择;图快又确定无结构变化,strings.Replacer 更省心。两者不互斥,但别指望用 Replacer 模拟 template 的语义。










