去提问»
提问背景 Question:
// Article 对应 cms_article 表及关联标签 type Article struct { ID int Question string Title string Description string Content template.HTML // 使用 template.HTML 避免 HTML 标签被转义 ClickCount int LikeCount int CreatedAt string Tags []Tag } 没有错,结构体没错

Go Markdown渲染不生效排查指南

发布时间:2026-08-18 11:30 👁️ 阅读:1

既然您的 Article 结构体中的 Content 字段已经确认是 template.HTML,且 ConvertMarkdown 也正确返回了 template.HTML,那么“没有效果”通常不是 Go 后端转换逻辑的问题,而是由以下 3 个最容易被忽视的客户端或前端细节 导致的。

请按照以下步骤依次排查,95% 的概率是由于 原因一(Tailwind CSS 样式重置) 引起的。


原因一:Tailwind CSS 的样式重置(最常见原因)

现象:查看网页源代码,发现 Markdown 已经被成功转换成了 <h1><ul><li><p> 等 HTML 标签,但是在浏览器页面上,标题没有加粗变大,列表没有圆点,段落之间没有间距,看着跟普通文本一模一样。

原因:Tailwind CSS 默认启用了 Preflight(样式重置),它会抹去所有 HTML 标签的原生样式。因此,即使 Goldmark 渲染出了标准的 HTML 标签,页面上也不会显示任何特殊样式。

解决方案:

  1. 引入 Tailwind Typography 插件(推荐)
    在 Tailwind 配置文件中引入 @tailwindcss/typography 插件,然后在包裹 Markdown 内容的 div 标签上加上 prose 类名:

    <!-- 必须加上 prose 类名,Tailwind 才会为内部的 h1, p, ul 等标签渲染样式 -->
    <div class="prose prose-slate max-w-none md:prose-lg">
        {{.Article.Content}}
    </div>
    
  2. 临时手写 CSS 方案(无需安装插件)
    如果您暂时没有配置前端构建流,可以直接在模板的 <head> 中或内联样式里为渲染后的标签指定样式,或者使用一个简易的 CSS 样式表覆盖它:

    <style>
        .markdown-content h1 { font-size: 2rem; font-weight: bold; margin-top: 1.5rem; margin-bottom: 0.5rem; }
        .markdown-content h2 { font-size: 1.5rem; font-weight: bold; margin-top: 1.25rem; margin-bottom: 0.5rem; }
        .markdown-content p { margin-bottom: 1rem; line-height: 1.6; color: #374151; }
        .markdown-content ul { list-style-type: disc; margin-left: 1.5rem; margin-bottom: 1rem; }
        .markdown-content code { background-color: #f3f4f6; padding: 0.2rem 0.4rem; border-radius: 0.25rem; font-family: monospace; }
        .markdown-content pre { background-color: #1f2937; color: #f9fafb; padding: 1rem; border-radius: 0.375rem; overflow-x: auto; margin-bottom: 1rem; }
    </style>
    <div class="markdown-content">
        {{.Article.Content}}
    </div>
    

原因二:Go 模板渲染变量路径不匹配

现象:页面中相关区域完全是一片空白,什么内容都没有显示出来。

原因:在 Go 后端中,您封装的数据结构是:

data := BaikeDetailData{
    Article: a,
    Tags:    tags,
}

如果您的 HTML 模板写成了 {{.Content}},Go 模板引擎将找不到该字段(因为 ContentArticle 结构体内)。

解决方案:

baike_detail.html 模板中,调用文章内容必须写成 {{.Article.Content}}

<!-- 错误写法 -->
<div>{{.Content}}</div>

<!-- 正确写法 -->
<div class="prose">
    {{.Article.Content}}
</div>

原因三:Goldmark 默认过滤了 HTML 安全标签

现象:Markdown 中如果夹杂了原生的 HTML 代码(例如插入的 iframe、一些自定义的 div),渲染后这些 HTML 代码直接消失了。

原因:Goldmark 为了防止 XSS 攻击,默认不会渲染 Markdown 中夹杂的原始 HTML 标签。

解决方案:

如果您确信数据库中的内容是安全的(例如是您自己或者管理员录入的高价值 AI 内容),可以在初始化 Goldmark 时开启 WithRendererOptions 允许 HTML 渲染:

import (
	"bytes"
	"html/template"
	"github.com/yuin/goldmark"
	"github.com/yuin/goldmark/renderer/html"
)

func ConvertMarkdown(mdContent string) template.HTML {
	var buf bytes.Buffer
	// 创建一个允许渲染原始 HTML 的 goldmark 实例
	md := goldmark.New(
		goldmark.WithRendererOptions(
			html.WithUnsafe(), // 允许渲染未经过滤的 HTML,避免部分样式或媒体元素丢失
		),
	)
	
	if err := md.Convert([]byte(mdContent), &buf); err != nil {
		return template.HTML(mdContent)
	}
	return template.HTML(buf.String())
}

💡 排查建议(3步诊断法)

  1. 在浏览器页面上右键点击 -> “查看网页源代码”
  2. 搜索您的文章内容,看里面是不是已经变成了 <h1><p> 等标签。
    • 如果源码里还是原始的 # 号和 **:说明 Go 后端的 ConvertMarkdown 函数没有执行成功,或者传入的文本为空。
    • 如果源码里变成了 &lt;h1&gt; 这样的转义字符:说明 Go 模板中的字段没有被识别为 template.HTML 类型,通常是模板里误加了 | html 过滤器或后端赋值类型错误。
    • 如果源码里已经是标准的 <h1><p> 标签,但页面显示毫无格式:说明 100% 是 原因一(Tailwind 样式被清除),请直接套用上述的 .markdown-content CSS 样式即可解决!