提问背景 Question:
你提供的是下面这样的,不对吧,\n怎么没有 “”是什么总理 ,是不是你给我的内容本身就转义了。显示不出来了,这是代码好不好
func ConvertMarkdown(mdContent string) template.HTML {
// 1. 将字面量的 "" (反斜杠+n) 替换为真正的换行符 ""
mdContent = strings.ReplaceAll(mdContent, "", "")
// 2. 兼容性处理:将字面量的 "\\r" 替换为真正的 "\r"
mdContent = strings.ReplaceAll(mdContent, "\\r", "")
// 3. 兼容性处理:将 Windows 换行符统一替换为 Linux 换行符(可选,防患未然)
mdContent = strings.ReplaceAll(mdContent, "\r", "")
var buf bytes.Buffer
if err := goldmark.Convert([]byte(mdContent), &buf); err != nil {
return template.HTML(mdContent) // 如果解析失败,回退返回原始文本
}
return template.HTML(buf.String())
}
修复Golang换行符解析问题
确实是这样,刚才的代码由于 JSON 序列化和 Markdown 渲染的多次转义,导致原本应该显示的 "\ "(反斜杠和 n)被吞掉变成了空字符串 ""。
在 Go 语言中,为了将数据库中读取到的字面量 (即由字符 \ 和 n 组成的两个字符)还原成真实的换行符(即 ASCII 码中的 LF),我们需要使用正确的双重转义。
以下是修改后完全正确的 ConvertMarkdown 函数代码:
package main
import (
"bytes"
"html/template"
"strings"
"github.com/yuin/goldmark"
)
// ConvertMarkdown 解析Markdown并转义为 template.HTML
func ConvertMarkdown(mdContent string) template.HTML {
// 1. 将字面量的 "\
"(两个字符:反斜杠 + n)替换为真正的换行符 "
"
// 在 Go 的双引号字符串中,两个反斜杠 "\\\
" 代表匹配文本中的
字符,单个 "
" 代表真正的换行
mdContent = strings.ReplaceAll(mdContent, "\
", "
")
// 2. 将字面量的 "\
" 替换为真正的回车符 "
"
mdContent = strings.ReplaceAll(mdContent, "\
", "
")
var buf bytes.Buffer
// 使用 goldmark 将规范化后的 Markdown 文本转换为 HTML 格式
if err := goldmark.Convert([]byte(mdContent), &buf); err != nil {
return template.HTML(mdContent) // 如果解析失败,回退返回原始文本
}
return template.HTML(buf.String())
}
💡 为什么会出现这个问题?
- 数据库存储了转义字符:AI 生成内容或者前端通过 JSON 提交内容时,由于 JSON 规范,换行符被自动转义成了可视化字符
(即一个反斜杠\和一个字符n,占用 2 个字节)。 - Goldmark 无法识别:Goldmark 等 Markdown 解析器在解析时,只认真正的换行符(ASCII 10,即
0x0A)。它看到这两个普通字符时,会当成普通文本,从而导致整篇文档堆积在了一起,标题、列表等所有排版全部失效。 - Go代码中的表达:在 Go 语言中,
"\ "才能代表那两个物理字符(反斜杠和n),通过strings.ReplaceAll将其全局替换成代表真正换行符的" ",即可彻底解决此问题。