Go写入中文需确保UTF-8编码一致、用os.Create+WriteString或os.OpenFile追加,并配合bufio.NewWriter提升性能。

Go 语言写入中文内容本身没有特殊限制,只要文件编码是 UTF-8、写入方式正确,中文就能正常保存和读取。关键不在 Go 本身,而在你如何打开文件、用什么方式写、以及文件保存时的编码是否一致。
确保源文件和目标文件都是 UTF-8 编码
Go 源码文件必须保存为 UTF-8(无 BOM),否则字符串字面量里的中文可能被解析错误。编辑器右下角通常显示当前编码,VS Code/GoLand 点击即可切换;若显示 ANSI 或 GBK,写进去的 "你好" 在运行时可能变成乱码或编译失败。
- 终端或 IDE 新建的 .go 文件默认是 UTF-8,但粘贴内容时可能带入非 UTF-8 字符 —— 建议用
file -i filename.go(Linux/macOS)或 VS Code 的编码提示确认 - 写入的目标文件(如
"log.txt")不需要手动加 BOM;UTF-8 不依赖 BOM,加了反而可能被某些程序误读 - 如果从外部读入文本再写入(比如读配置文件),要确认原始文件也是 UTF-8;否则
ioutil.ReadFile读出来就是错的字节,再怎么写都救不回来
用 os.Create + WriteString 是最稳妥的文本写入方式
直接用 ioutil.WriteFile 虽然简洁,但它会**完全覆盖**文件,且无法做追加、无法控制换行符风格(Windows CRLF vs Unix LF)、也不方便写多行内容。对中文文本,推荐显式打开文件 + WriteString:
file, err := os.Create("notes.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
_, err = file.WriteString("第一行:今天天气很好\n")
if err != nil {
log.Fatal(err)
}
_, err = file.WriteString("第二行:Go 支持中文 ✅\n")
if err != nil {
log.Fatal(err)
}
-
WriteString内部自动将字符串转为 UTF-8 字节流,无需手动调[]byte() - 每行结尾加
\n,避免 Windows 记事本打开时显示为一行(这是换行符问题,不是编码问题) - 不要省略
err检查 —— 中文内容较长时,磁盘满或权限不足容易在此处失败,但错误信息不会提示“中文导致”,容易误判
追加中文内容必须用 os.OpenFile 配合 os.O_APPEND
想在已有文件末尾加新日志或记录,不能用 os.Create(它会清空原文件),也不能用 ioutil.WriteFile(同样覆盖)。必须用 os.OpenFile 显式指定标志:
立即学习“go语言免费学习笔记(深入)”;
file, err := os.OpenFile("log.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
_, err = file.WriteString(fmt.Sprintf("[%s] 用户登录成功\n", time.Now().Format("2006-01-02 15:04:05")))
if err != nil {
log.Fatal(err)
}
-
os.O_CREATE确保文件不存在时自动创建 -
os.O_WRONLY表示只写,比os.O_RDWR更轻量;追加不需要读,别多开权限 - 注意:即使用了
os.O_APPEND,file.Seek依然能移动偏移量,但后续WriteString仍会强制写到末尾 —— 这是内核保证的,不用额外同步
大文件或高频写入时,务必套 bufio.NewWriter
频繁调 WriteString(比如每秒写几十次)会导致大量系统调用,性能骤降。这时应该用缓冲写入器:
file, _ := os.Create("big.txt")
defer file.Close()
writer := bufio.NewWriter(file)
defer writer.Flush() // 关键:必须调用,否则最后几KB可能丢失
for i := 0; i < 1000; i++ {
fmt.Fprintf(writer, "第%d条记录:数据已处理完毕\n", i)
}
-
bufio.NewWriter默认缓冲 4KB,适合中文文本(一个汉字占 3 字节,1000 个汉字才约 3KB) -
defer writer.Flush()必须放在defer file.Close()之前,否则Close()可能先触发,缓冲区没刷完就丢弃了 - 不要混用
file.WriteString和writer.WriteString—— 它们操作的是同一底层文件描述符,缓冲逻辑会冲突
最容易被忽略的一点:中文写入失败往往不是 Go 的问题,而是编辑器保存编码错了、或目标路径所在文件系统不支持长文件名(比如 FAT32 对 Unicode 支持不一致),建议先用最简代码写一个单行中文到临时路径,验证基础链路通不通,再往上加逻辑。


















