go中多行字符串首选反引号(raw string literal),因其原样保留换行缩进且免转义;需用strings.trimright去末尾换行,不可用+拼接变量,也不支持双引号内续行或插值。

Go 里写多行字符串只能用反引号?
不是只能,但绝大多数场景下,`(反引号)是唯一能原样保留换行、缩进和内部双引号的方案。Go 没有 Python 那种三重双引号或 Ruby 的 heredoc 语法,单引号只支持单字符,双引号里的 \n 要手动写、不可见换行、缩进混乱,维护起来极容易出错。
常见错误现象:"line1\nline2\n indented" 看似多行,实际源码里是一长串带转义的单行,可读性差;更糟的是复制粘贴 SQL 或 JSON 片段时,缩进空格被吃掉、引号要反复转义。
- 用
`包裹的字符串叫 raw string literal,不解析任何转义,换行、制表符、空格全保留 - 不能在其中直接写
`字符,否则提前终止;需要拼接或改用双引号 +\` - 如果字符串末尾有换行,它会算进字符串内容里——这点常被忽略,导致 HTTP 响应多一个空行或 YAML 解析失败
怎么去掉 raw string 末尾多余的换行?
Go 不提供内置 trim-trailing-newline 函数,但 strings.TrimRight 最简够用。别用 strings.TrimSpace,它会把开头的换行和空格也干掉,破坏缩进结构。
使用场景:模板化 SQL、嵌入 Markdown、生成配置文件——这些地方首行缩进有意义,但末尾空行纯属干扰。
立即学习“go语言免费学习笔记(深入)”;
示例:
sql := `SELECT * FROM users WHERE id = ? ` sql = strings.TrimRight(sql, "\n") // 只切末尾换行,保留前面所有空白
-
strings.TrimRight(sql, "\r\n")更健壮,兼容 Windows 行尾 - 如果字符串来自外部(如 embed.FS),建议在读取后立刻 trim,别留到拼接时再处理
- 别在每次使用前都 trim——性能无必要损耗;定义时就 trim 干净
嵌入变量时 raw string 还能用吗?
不能直接插值。`hello, ${name}` 这种写法 Go 不认。raw string 是字面量,编译期就定死,没有运行时插值机制。
常见错误现象:以为用 ` 就能像 JS 模板字符串一样写 `name: ${user.Name}`,结果编译报错 undefined: user 或直接当字面量输出。
- 老老实实用
fmt.Sprintf:先定义 raw string 模板,再用%s占位,fmt.Sprintf(template, name) - 复杂场景(如 HTML/SQL 拼接)考虑
text/template,但注意模板解析开销和安全(防注入) - 避免用
+拼接 raw string 和变量——类型不匹配,`a` + name会报错,必须显式转string(name)
为什么不用双引号加行连接符 \?
Go 不支持行连接符 \。写 "line1 \line2" 会直接编译失败,报错 non-declaration statement outside function body 或类似语法错误。
这是新手常踩的坑:从 C/C++ 或 Shell 转过来,下意识加反斜杠续行,结果卡在编译阶段。
- 双引号内换行必须显式写
\n,且整行必须在一行源码里,不能物理断行 - 想保持代码整洁?那就用
`,然后配合strings.ReplaceAll或正则做动态替换,而不是硬塞转义 - 某些 linter(如
golint)会警告过长字符串行,这时优先拆成 raw string + 变量拼接,而非妥协用\n
真正麻烦的不是语法本身,而是团队协作时有人坚持用双引号+\n,有人用 raw string 却忘了 trim 换行,导致同一份配置在不同环境表现不一致——这种差异往往藏得深,查半天才定位到字符串末尾那个看不见的 \n。










