如何在Golang中实现Markdown转HTML博客 Go语言Blackfriday库实战

blackfriday 已归档弃用,应改用 goldmark;其最小渲染仅需三行代码,但需注意扩展注册(如 table、codefence、gfm)、html 转义控制及 unsafe 选项的配套禁用。

如何在Golang中实现Markdown转HTML博客 Go语言Blackfriday库实战

blackfriday 已被弃用,别再用它了

Go 官方生态里 blackfriday 确实曾是 Markdown 渲染主力,但它早在 2020 年就正式归档(archived),不再维护。现在直接 go get github.com/russross/blackfriday/v2 虽能装上,但遇到 CommonMark 兼容性问题、安全更新缺失、HTML 实体处理异常时,没人修。

替代方案明确:用 goldmark —— 它是 Hugo 默认引擎,活跃维护,扩展性强,且 API 更符合 Go 的惯用写法。

goldmark 渲染 HTML 的最小可行代码

不加任何扩展、不改配置,只做基础转换,三行代码足够:

md := goldmark.New() var buf bytes.Buffer if err := md.Convert([]byte("# Hello"), &buf); err != nil {     log.Fatal(err) } html := buf.String() // "<h1>Hello</h1>" 
  • goldmark.New() 返回的是线程安全实例,可复用,别每次渲染都新建
  • md.Convert() 第二个参数必须是 io.Writerbytes.Buffer 最常用;别传 *strings.Builder,它不实现 Write() 方法
  • 输入字节切片不能是 nil,空字符串可以,但 nil 会 panic

启用代码高亮和表格支持要手动加扩展

默认 goldmark 不开语法糖:没有 <table>、没有 <code><pre class="brush:php;toolbar:false;">&lt;code class=&quot;go&quot;&gt;&lt;/code&gt;,得显式注册扩展模块。&lt;p&gt;&lt;span&gt;立即学习&lt;/span&gt;“&lt;a href=&quot;https://pan.quark.cn/s/00968c3c2c15&quot; style=&quot;text-decoration: underline !important; color: blue; font-weight: bolder;&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;go语言免费学习笔记(深入)&lt;/a&gt;”;&lt;/p&gt;&lt;div class=&quot;aritcle_card flexRow&quot;&gt; &lt;div class=&quot;artcardd flexRow&quot;&gt; &lt;a class=&quot;aritcle_card_img&quot; href=&quot;/ai/1404&quot; title=&quot;IBM Watson&quot;&gt;&lt;img src=&quot;https://img.php.cn/upload/ai_manual/001/431/639/68b6d12632818974.png&quot; alt=&quot;IBM Watson&quot; onerror=&quot;this.onerror='';this.src='/static/lhimages/moren/morentu.png'&quot; &gt;&lt;/a&gt; &lt;div class=&quot;aritcle_card_info flexColumn&quot;&gt; &lt;a href=&quot;/ai/1404&quot; title=&quot;IBM Watson&quot;&gt;IBM Watson&lt;/a&gt; &lt;p&gt;IBM Watson文字转语音&lt;/p&gt; &lt;/div&gt; &lt;a href=&quot;/ai/1404&quot; title=&quot;IBM Watson&quot; class=&quot;aritcle_card_btn flexRow flexcenter&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;span&gt;下载&lt;/span&gt; &lt;/a&gt; &lt;/div&gt; &lt;/div&gt;</pre> <ul> <li>表格:加 <code>extension.Table,否则 | a | b | 原样输出

  • 代码块高亮:需组合 extension.CodeFence + chroma.Highlighting(推荐 github.com/alecthomas/chroma
  • 注意顺序:WithExtensions() 必须在 goldmark.New() 里调用,不是链式调用在 Convert()
  • 常见错误:漏掉 extension.GFM —— 它是 GitHub Flavored Markdown 的聚合包,含表格、任务列表、脚注等,单独加 Table 不等于 GFM 全功能。

    HTML 输出不转义或 XSS 风险怎么控

    goldmark 默认对所有 HTML 标签做转义(比如把 <script></script> 变成 <script>),这安全但有时不想要——比如你信任源内容,想允许内联 <video></video> 或自定义组件。

    • 关闭全局转义:用 goldmark.WithRendererOptions(html.WithUnsafe())
    • 但别只加这一句:必须同时禁用 extension.Linkify(它会自动把 http 链接变 <a></a>,可能引入意外 href)
    • 更稳妥的做法是保留转义,仅对特定节点定制渲染器(如实现 RenderNode 接口),但复杂度陡增

    真正上线的博客系统,建议保持 WithUnsafe() 关闭,靠白名单机制(比如预处理阶段用正则提取并校验 <iframe src="https://youtube.com/embed/xxx"></iframe>)来放行可信标签。

    goldmark 的配置粒度很细,但多数人卡在“为什么我的表格没渲染”或“代码块没 class”这种地方——问题往往不在核心逻辑,而在扩展没注册全,或者用了旧文档里的 v1 写法。盯住 WithExtensionsWithRendererOptions 这两个入口点,比调参重要得多。