
使用 Go 的 html/template 包渲染 XML 会导致使用 go 的 `html/template` 包渲染 xml 会导致 `
在 Go 中生成符合规范的 XML(如 Sitemap 文件)时,切勿使用 html/template —— 它专为 HTML 输出设计,内置了上下文敏感的自动转义机制(如将 变成 <?xml ...>,使解析器直接拒收)。
✅ 正确方案一:改用 text/template
text/template 不执行任何自动转义,完全交由开发者控制输出内容,适合纯文本/XML/JSON 等非 HTML 场景:
package main import ( "bytes" "fmt" "text/template" // 注意:不是 html/template ) const tmplStr = `{{define "indexSitemap"}}<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> {{range .Sitemaps}} <sitemap><loc>{{.Loc}}</loc></sitemap> {{end}} </sitemapindex>{{end}}` type SitemapEntry struct { Loc string } type SitemapData struct { Sitemaps []SitemapEntry } func main() { tmpl, err := template.New("sitemap").Parse(tmplStr) if err != nil { panic(err) } data := SitemapData{ Sitemaps: []SitemapEntry{ {Loc: "https://www.test.com/sitemap.xml"}, {Loc: "https://www.test.com/events-sitemap.xml"}, {Loc: "https://www.test.com/gamesAndTeams-sitemap.xml"}, }, } var buf bytes.Buffer if err := tmpl.ExecuteTemplate(&buf, "indexSitemap", data); err != nil { panic(err) } fmt.Println(buf.String()) // 输出合法、可解析的 XML }⚠️ 注意事项:
- text/template 不提供安全防护,所有变量插入均为原始输出。若 .Loc 来自用户输入,必须手动校验/清理(如确保 URL 符合格式、不含非法 XML 字符);
- XML 声明 在 text/template 中可安全使用,不会被转义。
✅ 更优方案二:放弃模板,使用 encoding/xml(推荐)
对于结构固定的 XML(如 Sitemap),直接定义 Go 结构体并序列化 是最健壮、类型安全、无注入风险的方式:
Golang Uber Dig下载使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
package main import ( "encoding/xml" "fmt" ) type SitemapIndex struct { XMLName xml.Name `xml:"sitemapindex"` XMLNS string `xml:"xmlns,attr"` Sitemaps []Sitemap `xml:"sitemap"` } type Sitemap struct { Loc string `xml:"loc"` } func main() { sitemap := SitemapIndex{ XMLNS: "http://www.sitemaps.org/schemas/sitemap/0.9", Sitemaps: []Sitemap{ {Loc: "https://www.test.com/sitemap.xml"}, {Loc: "https://www.test.com/events-sitemap.xml"}, {Loc: "https://www.test.com/gamesAndTeams-sitemap.xml"}, }, } output, err := xml.MarshalIndent(sitemap, "", " ") if err != nil { panic(err) } // 添加 XML 声明前缀(xml.Marshal 不包含它) result := []byte(xml.Header + string(output)) fmt.Println(string(result)) }此方式优势显著:
- ✅ 自动生成合法转义(如
- ✅ 编译期类型检查,避免拼写错误或结构错位;
- ✅ 无需手动处理 CDATA、命名空间、编码声明等细节;
- ✅ 天然防御 XSS/XI(因不拼接原始字符串)。
总结
方案 安全性 维护性 适用场景 html/template ❌(强制转义破坏 XML) 低 仅限 HTML 输出 text/template ⚠️(需手动净化输入) 中 简单动态 XML,且输入完全可信 encoding/xml ✅(自动合规转义) 高 推荐!结构清晰、标准兼容、零配置 结论:生成 Sitemap 或其他标准 XML 文件,请优先使用 encoding/xml —— 它是 Go 生态中生成正确、安全、可维护 XML 的黄金标准。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











