最省事的是用 golang.org/x/text 的 textwrap.wrap,它按 unicode 字符计数、不拆单词或中文字符,但需安装 go get golang.org/x/text;若避免依赖可手动实现,注意中文宽度须用 runewidth.stringwidth 计算,并预处理零宽字符。

用 textwrap.Wrap 最省事,但得自己装包
Go 标准库没有内置的自动折行函数,textwrap 是社区广泛采用的轻量方案(来自 golang.org/x/text 子模块)。它不处理 Unicode 组合字符或双向文本,但对普通英文、数字、ASCII 标点和常见中文完全够用。
安装命令:
go get golang.org/x/text注意不是
golang.org/x/text/width 或其他子路径——主包导入后才能用 textwrap。
关键点:
-
textwrap.Wrap默认按 Unicode 字符计数,不是字节,所以中文、emoji 都算 1 个“宽度” - 它不会拆开单词(英文)或单个中文字符(中文),但会在空格、制表符、换行符处断行
- 如果某一行纯是超长无空格字符串(比如 base64 或长 URL),它会硬截断——这不是 bug,是设计如此
手动实现简单折行:用 strings.FieldsFunc + strings.Builder
不想引入外部依赖时,可以自己控制逻辑。核心思路是:按空格切分,逐个累加,超宽就换行。
示例逻辑(不处理中英文混排细节):
func wrapText(s string, width int) string {
fields := strings.FieldsFunc(s, func(r rune) bool { return r == '\n' || r == '\r' })
var out strings.Builder
for _, line := range fields {
words := strings.Fields(line)
var current strings.Builder
for i, w := range words {
if i > 0 && current.Len()+len(w)+1 > width {
out.WriteString(current.String())
out.WriteByte('\n')
current.Reset()
}
if current.Len() > 0 {
current.WriteByte(' ')
}
current.WriteString(w)
}
if current.Len() > 0 {
out.WriteString(current.String())
}
out.WriteByte('\n')
}
return strings.TrimSuffix(out.String(), "\n")
}
注意:
- 这个版本不保留原始缩进,也不处理制表符对齐
-
len(w)对中文返回字节数(如 "你好" 是 6),不是字符数——若需按显示宽度,必须用runewidth.StringWidth替代 - 性能上,对几 MB 的文本会明显慢于
textwrap,因反复分配strings.Builder
处理中文等双字节文字:必须用 runewidth.StringWidth
单纯用 len() 或 utf8.RuneCountInString() 都不准:中文字符显示占 2 列,但 len("中") == 3,utf8.RuneCountInString("中") == 1,而终端里它实际占 2 个位置。
解决方案是引入 github.com/mattn/go-runewidth:
-
runewidth.StringWidth("中文a")返回5(2+2+1) - 折行前,对每个词调用该函数累加宽度,而非用
len() - 特别注意:全角标点(,。!)也占 2 宽度;半宽空格占 1,全宽空格( )占 2
否则在终端或固定宽度 UI 中,中文会严重溢出或错位。
别忽略 \t 和 \u200b 这类隐形字符
真实业务文本常含不可见字符:\t 在折行时会被当普通空格处理(多数情况 OK),但零宽空格 \u200b、零宽连接符 \u200d 会让 strings.Fields 失效,导致整段被当一个“词”,最终硬截断。
建议预处理:
- 用
strings.Map清理掉\u200b-\u200f、\u202a-\u202e等控制符 - 把
\t替换成空格(除非你明确需要保留制表语义) - 如果源数据来自富文本粘贴(如微信、网页),还可能有
\uFEFF(BOM)或\u00A0(不换行空格),也要一并 normalize
这些字符不报错,但会让折行结果在视觉上突然错乱,而且很难复现——往往只出现在特定用户输入里。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











