Go模板应放当前工作目录下,推荐用embed.FS编译进二进制;传结构体字段前需预处理防nil panic;生成Go代码须严格控制换行缩进并用gofmt校验;多语言模板应分实例、自定义分隔符及FuncMap。
模板文件该放在哪里才能被
正确加载
Go 的
默认按相对路径查找,且路径基准是**当前工作目录(
)**,不是源码所在目录或二进制所在目录。很多人把模板放
,却在项目根目录外执行命令(比如从 IDE 启动、CI 环境中),导致
。
实操建议:
用
(Go 1.16+)将模板编译进二进制,避免运行时路径依赖:
若坚持用文件系统,统一用
推导模板根目录(注意
返回的是调用者位置,需确保在包初始化或主函数中调用)
不要硬编码
—— 它在 Docker 容器里、Windows 和 macOS 下行为不一致
如何安全传递结构体字段到模板,避免
生成器常基于 struct 生成代码,但字段可能为 nil(如指针字段、可选嵌套结构)。模板里直接写
会 panic,而
又容易漏掉空值判断逻辑。
立即学习
“
go语言免费学习笔记(深入)
”;
实操建议:
在模板中统一用
,不依赖
的作用域收缩
更可靠的做法是在传入数据前做预处理:用一个中间 struct 封装原始数据,所有字段都转为非 nil 类型(例如
→
,空则设为
;
→
判断)
对必须保留 nil 语义的字段(如 “显式不生成某段代码”),定义自定义方法,比如
,模板里调用
生成 Go 源码时,为什么
总失败?模板换行和缩进怎么控制
模板输出的 Go 代码如果缩进错乱、缺少换行、括号不匹配,
会拒绝格式化,甚至编译失败。常见原因是模板里混用
和
不当,或在
中没处理好行尾空白。
实操建议:
模板第一行用
抑制前置空白,最后一行用
显式加换行,确保输出以完整行结尾
对多行 Go 代码块(如
、
),用
+
拆分,每个
内部严格控制缩进,避免模板指令本身引入空格
生成后立即调用
校验:用
或更轻量的
包重写内容,别依赖人工检查
如何让生成器支持多语言模板(Go / SQL / YAML)共存而不互相污染
一个生成器常要同时产出 Go 结构体、SQL DDL、OpenAPI YAML。如果全塞进一个
,函数名冲突(比如
在 Go 模板里转蛇形,在 SQL 模板里可能要大写)、分隔符冲突(YAML 的
和 Go 模板冲突)、甚至注释语法打架。
实操建议:
为每种目标语言创建独立的
实例,用不同
注册各自专用函数(
、
、
)
YAML 模板务必改用
并自定义分隔符:
,避免和 YAML 字面量中的
冲突
不要复用同一个
——
对 Go 代码可能是错的(如包名应小写),对 SQL 却是合理的
模板不是写一次就完事的工具,它和生成逻辑耦合越深,后期维护成本越高。最常被忽略的是错误位置映射:模板出错时,
只报第几行,但你得知道这行对应的是原始模板文件哪一行 —— 所以永远用
包裹解析,别吞掉 parse error。
template.ParseFilestemplate.ParseFilesos.Getwd()./templates/xxx.tmplopen templates/xxx.tmpl: no such file or directoryembed.FSimport _ "embed"
//go:embed templates/*.tmpl
var tmplFS embed.FS
t := template.Must(template.New("").ParseFS(tmplFS, "templates/*.tmpl"))
filepath.Join(filepath.Dir(runtime.Caller(0)), "..", "templates")runtime.Caller"./templates"template: xxx: nil pointer evaluating interface {}.YYY{{.Field.Name}}{{with .Field}}{{.Name}}{{end}}{{if .Field}}{{.Field.Name}}{{else}}""{{end}}with*stringstring""[]intlen() > 0func (s *MySpec) HasDescription() bool { return s.Description != nil }{{if .HasDescription}}go fmtgo fmt{{- }}{{ }}range{{- /* */}}{{- "\n"}}funcstruct{{- define "xxx" -}}{{template "xxx" .}}definegofmtexec.Command("gofmt", "-w", outputPath)go/formattemplate.Templatesnake{{*template.TemplateFuncMapgo_snakesql_upperyaml_quotetext/templatet := template.New("yaml").Delims("${", "}"){{template.FuncMapstrings.ToUppertemplate.Errortemplate.Must