一只用 AI Agent 搭副业产线的程序员前几篇我们把 Prompt 从「聊天框里的口语」升级成了「有结构的指令」。但还有一个问题没解决你的 Prompt 里有很多重复的部分。每次改一个变量要全文搜索替换。想在 Prompt 里加条件逻辑一堆if嵌在fmt.Sprintf里越来越像意大利面条。这篇文章给你一个可复用的 Prompt 模板引擎。不到 200 行 Go 代码但足以覆盖 90% 的 Prompt 管理需求。Prompt 模板的三种需求看看这三个 Prompt 草稿// 场景 1代码审查 Prompt 根据语言不同规则不同 如果是 Go → 检查 goroutine 泄漏 如果是 Python → 检查 GIL 相关问题 // 场景 2日报生成要根据仓库数量动态调整 如果只有 1 个仓库 → 今日工作内容 如果有 3 个仓库 → 今日多项目工作内容 // 场景 3数据分析需要循环遍历字段 对以下 5 个指标逐一分析趋势 - 指标 1DAU - 指标 2收入 ...这三个场景概括了 Prompt 模板化需要的三种能力变量替换——{{.UserName}}→ 张三条件分支——{{if .HasBugs}}列出 Bug{{end}}循环遍历——{{range .Metrics}}{{.Name}}{{end}}直接用 Go 的text/templateGo 标准库的text/template天然支持这三种能力。我们不需要从头写一个引擎——直接封装它packagepromptimport(bytesstringstext/template)// PromptEngine 管理所有的 Prompt 模板typePromptEnginestruct{templates*template.Template funcMap template.FuncMap}funcNew()*PromptEngine{funcMap:template.FuncMap{// 自定义函数转为 JSONjson:func(vinterface{})string{b,_:json.Marshal(v)returnstring(b)},// 自定义函数缩进indent:func(sstring,spacesint)string{prefix:strings.Repeat( ,spaces)lines:strings.Split(s,\n)fori,line:rangelines{lines[i]prefixline}returnstrings.Join(lines,\n)},// 自定义函数代码块包裹codeblock:func(lang,codestring)string{returnlang\ncode\n},}pe:PromptEngine{funcMap:funcMap,}pe.templatestemplate.New(prompt).Funcs(funcMap)returnpe}变量替换最基础的能力// 注册一个模板func(pe*PromptEngine)AddTemplate(name,tmplstring)error{_,err:pe.templates.New(name).Parse(tmpl)returnerr}// 渲染模板func(pe*PromptEngine)Render(namestring,datainterface{})(string,error){varbuf bytes.Buffer err:pe.templates.ExecuteTemplate(buf,name,data)iferr!nil{return,err}returnbuf.String(),nil}使用pe:prompt.New()// 定义模板pe.AddTemplate(code-gen,你是 {{.Role}}擅长 {{.Language}} 开发。 任务{{.Task}} 要求 - 语言{{.Language}} - 框架{{.Framework}} - 输出{{if .WithTests}}包含单元测试{{else}}只输出业务代码{{end}} )// 渲染result,_:pe.Render(code-gen,map[string]interface{}{Role:Go 后端开发专家,Language:Go,Task:实现一个 JWT 认证中间件,Framework:gin,WithTests:true,})输出你是 Go 后端开发专家擅长 Go 开发。 任务实现一个 JWT 认证中间件 要求 - 语言Go - 框架gin - 输出包含单元测试变量替换解决了一次写模板、多次用不同数据填充的问题。条件分支根据上下文裁剪 Prompt这是 Prompt 模板化最有用的能力。看一个代码审查的例子pe.AddTemplate(code-review,你是代码审查专家。审查以下 {{.Language}} 代码 {{codeblock .Language .Code}} 请重点关注以下方面 {{if .CheckSecurity}} - SQL 注入、XSS、命令注入等安全漏洞 {{end}} {{if .CheckPerformance}} - 性能瓶颈不必要的内存分配、低效的循环、缺少并发 {{end}} {{if .CheckStyle}} - 代码风格命名规范、注释完整性、函数长度 {{end}} {{if .CheckConcurrency}} - 并发问题数据竞争、死锁、goroutine 泄漏 {{end}} {{if not .CheckSecurity and not .CheckPerformance and not .CheckStyle and not .CheckConcurrency}} - 通用代码质量问题 {{end}} 输出格式{{.OutputFormat}} )// Go 代码审查——关注并发和安全result1,_:pe.Render(code-review,map[string]interface{}{Language:Go,Code:goCode,CheckSecurity:true,CheckPerformance:false,CheckStyle:false,CheckConcurrency:true,OutputFormat:每个问题一行格式[严重程度] 文件名:行号 - 问题描述,})同一个模板勾选不同的审查维度生成不同的 System Prompt。你不用维护 4 个版本的审查 Prompt 了一个模板搞定。循环遍历批量生成 Prompt 片段比如数据分析场景pe.AddTemplate(data-analysis,你是一个数据分析师。分析以下数据 数据源 {{range .DataSources}} - {{.Name}}{{.Description}}时间范围{{.TimeRange}} {{end}} 分析指标共 {{len .Metrics}} 个 {{range $i, $m : .Metrics}} 指标 {{add $i 1}}{{$m.Name}} 定义{{$m.Definition}} 目标值{{$m.Target}} {{if $m.Alert}}⚠️ 如果低于 {{$m.Alert}} 需要重点关注{{end}} {{end}} 请给出 1. 每个指标的趋势判断上升/下降/持平 2. 异常指标的根因分析 3. 改进建议 )注意这里用了len和自定义的add函数Go template 里没有1需要用add函数。在 FuncMap 里加上add:func(a,bint)int{returnab},模板继承一个 System Prompt 基类当你有 10 个不同的 Agent 时会发现它们的 System Prompt 有一段公共的「基础规则」——不要编造、输出格式、语气要求等。用 Go template 的block和template实现继承// 基础模板pe.AddTemplate(base-system,{{block role .}}你是 AI 编程助手。{{end}} 通用规则 1. 不确定的 API 直接说「不确定」不要编造 2. 代码完整可编译包含必要的 import 3. 中文回答代码注释也用中文 {{block specialty .}}{{end}} 输出约束 - 代码用 {{block lang .}}Go{{end}} 代码块 - 不要输出额外的解释文字{{block extra .}}{{end}} )// 代码审查 Agent —— 继承基础模板pe.AddTemplate(reviewer-system,{{template base-system .}} {{define role}}你是代码审查员专门审查 Go 代码的安全和性能问题。{{end}} {{define specialty}} 审查规则 - 高危问题 中危问题 低危问题 - 每个问题标注行号 - 提供具体的修复代码 {{end}} )// 文档写手 Agent —— 同一个基础模板不同角色pe.AddTemplate(doc-writer-system,{{template base-system .}} {{define role}}你是技术文档写手擅长写 Go godoc 风格注释。{{end}} {{define specialty}} 写作规则 - 每行注释不超过 80 字符 - 参数说明用「参数名: 说明」格式 - 返回值说明用「返回: 说明」格式 {{end}} )两个 Agent 共享同一套基础规则各自定义差异部分。基础规则变了→改一处→所有 Agent 同步更新。完整封装PromptManager最后把模板引擎嵌入到之前的 PromptManager 里typePromptManagerstruct{engine*PromptEngine config*Config// 上篇文章的 JSON 配置}func(pm*PromptManager)BuildPrompt(roleKey,templateNamestring,datainterface{})([]Message,float64,int,error){role:pm.config.Roles[roleKey]// 渲染 System Prompt 模板systemPrompt,err:pm.engine.Render(system-templateName,data)iferr!nil{returnnil,0,0,err}// 渲染 User Prompt 模板userPrompt,err:pm.engine.Render(user-templateName,data)iferr!nil{returnnil,0,0,err}return[]Message{{Role:system,Content:systemPrompt},{Role:user,Content:userPrompt},},role.Temperature,role.MaxTokens,nil}使用时pm:NewPromptManager(roles.json)data:map[string]interface{}{Language:Go,Code:myCode,CheckConcurrency:true,}messages,temp,maxTok,_:pm.BuildPrompt(code-reviewer,go-review,data)result:callLLM(messages,temp,maxTok)模板引擎的边界这个引擎适合管理10-50 个 Prompt 模板的场景。如果你有上百个模板、需要版本管理、需要模板市场——那可能需要更重的方案。但对大多数开发场景来说text/template JSON 配置 泛型结构化输出已经足够覆盖日常了。一句话总结把 Prompt 从字符串拼接升级到模板引擎你就真的在「写 Prompt 代码」而不是「写 Prompt 文本」了。下一篇我们搞一个实用的技能——AI 不听话时的 7 步排查清单。每个步骤都有具体的操作指令帮你从「AI 怎么又犯病了」到「我知道为什么了」。关注我别错过。 一只用 AI Agent 搭副业产线的程序员全平台同名虾哥不加班需要定制 AI 工具来聊聊 → lob_ai源码GitHub - lobster-bujiaban/goprompt
用 Go 写一个 Prompt 模板引擎:支持变量、条件和循环
一只用 AI Agent 搭副业产线的程序员前几篇我们把 Prompt 从「聊天框里的口语」升级成了「有结构的指令」。但还有一个问题没解决你的 Prompt 里有很多重复的部分。每次改一个变量要全文搜索替换。想在 Prompt 里加条件逻辑一堆if嵌在fmt.Sprintf里越来越像意大利面条。这篇文章给你一个可复用的 Prompt 模板引擎。不到 200 行 Go 代码但足以覆盖 90% 的 Prompt 管理需求。Prompt 模板的三种需求看看这三个 Prompt 草稿// 场景 1代码审查 Prompt 根据语言不同规则不同 如果是 Go → 检查 goroutine 泄漏 如果是 Python → 检查 GIL 相关问题 // 场景 2日报生成要根据仓库数量动态调整 如果只有 1 个仓库 → 今日工作内容 如果有 3 个仓库 → 今日多项目工作内容 // 场景 3数据分析需要循环遍历字段 对以下 5 个指标逐一分析趋势 - 指标 1DAU - 指标 2收入 ...这三个场景概括了 Prompt 模板化需要的三种能力变量替换——{{.UserName}}→ 张三条件分支——{{if .HasBugs}}列出 Bug{{end}}循环遍历——{{range .Metrics}}{{.Name}}{{end}}直接用 Go 的text/templateGo 标准库的text/template天然支持这三种能力。我们不需要从头写一个引擎——直接封装它packagepromptimport(bytesstringstext/template)// PromptEngine 管理所有的 Prompt 模板typePromptEnginestruct{templates*template.Template funcMap template.FuncMap}funcNew()*PromptEngine{funcMap:template.FuncMap{// 自定义函数转为 JSONjson:func(vinterface{})string{b,_:json.Marshal(v)returnstring(b)},// 自定义函数缩进indent:func(sstring,spacesint)string{prefix:strings.Repeat( ,spaces)lines:strings.Split(s,\n)fori,line:rangelines{lines[i]prefixline}returnstrings.Join(lines,\n)},// 自定义函数代码块包裹codeblock:func(lang,codestring)string{returnlang\ncode\n},}pe:PromptEngine{funcMap:funcMap,}pe.templatestemplate.New(prompt).Funcs(funcMap)returnpe}变量替换最基础的能力// 注册一个模板func(pe*PromptEngine)AddTemplate(name,tmplstring)error{_,err:pe.templates.New(name).Parse(tmpl)returnerr}// 渲染模板func(pe*PromptEngine)Render(namestring,datainterface{})(string,error){varbuf bytes.Buffer err:pe.templates.ExecuteTemplate(buf,name,data)iferr!nil{return,err}returnbuf.String(),nil}使用pe:prompt.New()// 定义模板pe.AddTemplate(code-gen,你是 {{.Role}}擅长 {{.Language}} 开发。 任务{{.Task}} 要求 - 语言{{.Language}} - 框架{{.Framework}} - 输出{{if .WithTests}}包含单元测试{{else}}只输出业务代码{{end}} )// 渲染result,_:pe.Render(code-gen,map[string]interface{}{Role:Go 后端开发专家,Language:Go,Task:实现一个 JWT 认证中间件,Framework:gin,WithTests:true,})输出你是 Go 后端开发专家擅长 Go 开发。 任务实现一个 JWT 认证中间件 要求 - 语言Go - 框架gin - 输出包含单元测试变量替换解决了一次写模板、多次用不同数据填充的问题。条件分支根据上下文裁剪 Prompt这是 Prompt 模板化最有用的能力。看一个代码审查的例子pe.AddTemplate(code-review,你是代码审查专家。审查以下 {{.Language}} 代码 {{codeblock .Language .Code}} 请重点关注以下方面 {{if .CheckSecurity}} - SQL 注入、XSS、命令注入等安全漏洞 {{end}} {{if .CheckPerformance}} - 性能瓶颈不必要的内存分配、低效的循环、缺少并发 {{end}} {{if .CheckStyle}} - 代码风格命名规范、注释完整性、函数长度 {{end}} {{if .CheckConcurrency}} - 并发问题数据竞争、死锁、goroutine 泄漏 {{end}} {{if not .CheckSecurity and not .CheckPerformance and not .CheckStyle and not .CheckConcurrency}} - 通用代码质量问题 {{end}} 输出格式{{.OutputFormat}} )// Go 代码审查——关注并发和安全result1,_:pe.Render(code-review,map[string]interface{}{Language:Go,Code:goCode,CheckSecurity:true,CheckPerformance:false,CheckStyle:false,CheckConcurrency:true,OutputFormat:每个问题一行格式[严重程度] 文件名:行号 - 问题描述,})同一个模板勾选不同的审查维度生成不同的 System Prompt。你不用维护 4 个版本的审查 Prompt 了一个模板搞定。循环遍历批量生成 Prompt 片段比如数据分析场景pe.AddTemplate(data-analysis,你是一个数据分析师。分析以下数据 数据源 {{range .DataSources}} - {{.Name}}{{.Description}}时间范围{{.TimeRange}} {{end}} 分析指标共 {{len .Metrics}} 个 {{range $i, $m : .Metrics}} 指标 {{add $i 1}}{{$m.Name}} 定义{{$m.Definition}} 目标值{{$m.Target}} {{if $m.Alert}}⚠️ 如果低于 {{$m.Alert}} 需要重点关注{{end}} {{end}} 请给出 1. 每个指标的趋势判断上升/下降/持平 2. 异常指标的根因分析 3. 改进建议 )注意这里用了len和自定义的add函数Go template 里没有1需要用add函数。在 FuncMap 里加上add:func(a,bint)int{returnab},模板继承一个 System Prompt 基类当你有 10 个不同的 Agent 时会发现它们的 System Prompt 有一段公共的「基础规则」——不要编造、输出格式、语气要求等。用 Go template 的block和template实现继承// 基础模板pe.AddTemplate(base-system,{{block role .}}你是 AI 编程助手。{{end}} 通用规则 1. 不确定的 API 直接说「不确定」不要编造 2. 代码完整可编译包含必要的 import 3. 中文回答代码注释也用中文 {{block specialty .}}{{end}} 输出约束 - 代码用 {{block lang .}}Go{{end}} 代码块 - 不要输出额外的解释文字{{block extra .}}{{end}} )// 代码审查 Agent —— 继承基础模板pe.AddTemplate(reviewer-system,{{template base-system .}} {{define role}}你是代码审查员专门审查 Go 代码的安全和性能问题。{{end}} {{define specialty}} 审查规则 - 高危问题 中危问题 低危问题 - 每个问题标注行号 - 提供具体的修复代码 {{end}} )// 文档写手 Agent —— 同一个基础模板不同角色pe.AddTemplate(doc-writer-system,{{template base-system .}} {{define role}}你是技术文档写手擅长写 Go godoc 风格注释。{{end}} {{define specialty}} 写作规则 - 每行注释不超过 80 字符 - 参数说明用「参数名: 说明」格式 - 返回值说明用「返回: 说明」格式 {{end}} )两个 Agent 共享同一套基础规则各自定义差异部分。基础规则变了→改一处→所有 Agent 同步更新。完整封装PromptManager最后把模板引擎嵌入到之前的 PromptManager 里typePromptManagerstruct{engine*PromptEngine config*Config// 上篇文章的 JSON 配置}func(pm*PromptManager)BuildPrompt(roleKey,templateNamestring,datainterface{})([]Message,float64,int,error){role:pm.config.Roles[roleKey]// 渲染 System Prompt 模板systemPrompt,err:pm.engine.Render(system-templateName,data)iferr!nil{returnnil,0,0,err}// 渲染 User Prompt 模板userPrompt,err:pm.engine.Render(user-templateName,data)iferr!nil{returnnil,0,0,err}return[]Message{{Role:system,Content:systemPrompt},{Role:user,Content:userPrompt},},role.Temperature,role.MaxTokens,nil}使用时pm:NewPromptManager(roles.json)data:map[string]interface{}{Language:Go,Code:myCode,CheckConcurrency:true,}messages,temp,maxTok,_:pm.BuildPrompt(code-reviewer,go-review,data)result:callLLM(messages,temp,maxTok)模板引擎的边界这个引擎适合管理10-50 个 Prompt 模板的场景。如果你有上百个模板、需要版本管理、需要模板市场——那可能需要更重的方案。但对大多数开发场景来说text/template JSON 配置 泛型结构化输出已经足够覆盖日常了。一句话总结把 Prompt 从字符串拼接升级到模板引擎你就真的在「写 Prompt 代码」而不是「写 Prompt 文本」了。下一篇我们搞一个实用的技能——AI 不听话时的 7 步排查清单。每个步骤都有具体的操作指令帮你从「AI 怎么又犯病了」到「我知道为什么了」。关注我别错过。 一只用 AI Agent 搭副业产线的程序员全平台同名虾哥不加班需要定制 AI 工具来聊聊 → lob_ai源码GitHub - lobster-bujiaban/goprompt