用 encoding/xml 生成合法 RSS 2.0 需严格遵循规范:根节点为 , 必含 、、,每个 至少含 、、; 须用 time.RFC1123 格式;HTTP 输出需设 application/rss+xml; charset=utf-8 头并用 xml.NewEncoder 流式编码。

如何用 encoding/xml 生成合法 RSS 2.0 XML
RSS 2.0 是严格格式的 XML,直接拼接字符串极易出错(比如未转义字符、缺失必需字段、命名空间错误)。Golang 的 encoding/xml 包能自动处理转义和结构嵌套,但必须严格匹配 RSS 规范字段名与层级。
关键点:RSS 根节点是 ,必须带 version="2.0" 属性;子节点 内必须包含 、、;每个 至少含 、、(且 isPermaLink="false" 时需显式声明)。
示例结构定义:
type RSS struct {
XMLName xml.Name `xml:"rss"`
Version string `xml:"version,attr"`
Channel Channel `xml:"channel"`
}
type Channel struct {
Title string `xml:"title"`
Link string `xml:"link"`
Description string `xml:"description"`
Language string `xml:"language,omitempty"`
Items []Item `xml:"item"`
}
type Item struct {
Title string `xml:"title"`
Link string `xml:"link"`
Description string `xml:"description,omitempty"`
Guid Guid `xml:"guid"`
PubDate string `xml:"pubDate,omitempty"`
}
type Guid struct {
XMLName xml.Name `xml:"guid"`
IsPermaLink string `xml:"isPermaLink,attr"`
Value string `xml:",chardata"`
}
为什么 xml.Marshal 输出的 XML 常被 RSS 阅读器拒绝
常见原因不是语法错误,而是语义缺失或格式不合规:
立即学习“go语言免费学习笔记(深入)”;
-
必须是 RFC 2822 格式(如"Mon, 01 Jan 2024 12:00:00 GMT"),用time.Now().Format(time.RFC1123Z)会出错(缺少空格和时区缩写),正确用time.RFC1123 -
若设为isPermaLink="true",其值必须是可访问 URL;若只是唯一 ID,必须设isPermaLink="false"并确保Value字段非空 - 所有文本字段(如
Title、Description)若含 HTML 实体(如&、),xml.Marshal会自动转义,无需手动处理;但若传入已转义字符串(如"&"),会导致双重转义 - XML 声明
不是xml.Marshal自动添加的,需手动前置写入
如何在 HTTP handler 中安全输出 RSS feed
不能只写 w.Header().Set("Content-Type", "application/rss+xml") —— 缺少 charset 会导致中文乱码;也不能直接 xml.Marshal 后用 fmt.Fprint,易因错误中断导致半截 XML。
推荐做法:
- 设置完整 Header:
w.Header().Set("Content-Type", "application/rss+xml; charset=utf-8") - 用
xml.NewEncoder(w)替代xml.Marshal+io.WriteString,支持流式编码,内存友好且自动处理错误 - 对每个
Encode调用检查 error,一旦失败立即 return,避免输出残缺 XML - 若数据来自数据库或网络,务必加超时和 context 控制,防止 RSS 接口拖垮整个服务
简短 handler 示例:
func rssHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/rss+xml; charset=utf-8")
enc := xml.NewEncoder(w)
err := enc.Encode(rssData) // rssData 是已构造好的 RSS 结构体
if err != nil {
http.Error(w, "RSS encode failed", http.StatusInternalServerError)
return
}
}
本地调试时如何验证生成的 RSS 是否合格
浏览器直接打开 .xml 文件不可靠(多数现代浏览器不渲染 RSS);真实验证要分两步:
- 用
xmllint检查基础语法:xmllint --noout feed.xml。若报错,常见是 UTF-8 BOM 或非法字符混入 - 用在线 RSS 验证器(如 W3C Feed Validation Service)上传或提交 URL,它会检查
是否存在、数量是否合理、是否重复等业务逻辑规则 - 本地测试可配合
curl -H "Accept: application/rss+xml" http://localhost:8080/feed确认响应头和内容是否符合预期;注意不要漏掉charset=utf-8
RSS 表面简单,但阅读器实现差异大——有些强制要求 ,有些对 长度敏感。上线前至少用三个不同阅读器(如 NetNewsWire、Feedly、Inoreader)实测订阅效果。










