fmt.fprintf是写文件时唯一靠谱的选择,它真正解析格式动词如%d、%q并将值正确替换,而fmt.print类函数不解析格式串;写结构体推荐%+v(带字段名)或%#v(go字面量),需搭配bufio.writer提升性能并记得flush。

别用 fmt.Print 或 fmt.Println 往文件里写格式化内容——它们根本不解析 %s、%d 这类动词,只会把格式串原样输出,参数堆在后面,结果完全不可控。
为什么 fmt.Fprintf 是写文件时唯一靠谱的选择
fmt.Fprintf 接收一个实现了 io.Writer 的对象(比如 *os.File 或 *bufio.Writer)作为第一个参数,之后才是格式串和变量。它才是真正把 %d 替换成数字、%q 加上转义引号的函数。
-
fmt.Printf("id=%06d, name=%q", 123, "Alice")→ 输出到终端 -
fmt.Fprintf(file, "id=%06d, name=%q\n", 123, "Alice")→ 写入文件,且带换行 - 误用
fmt.Fprint(file, "id=%06d", 123)→ 文件里真会写出id=%06d123,不是你想要的
%v、%+v、%#v 写进文件时怎么选
结构体或复杂值写入日志文件或调试快照时,这三个动词差异直接决定你后续要不要重跑程序来确认字段值。
-
%v:只输出值,{123 "foo" true}—— 字段名全丢,查错靠猜 -
%+v:带字段名,{ID:123 Name:"foo" Active:true}—— 快速核对赋值是否到位 -
%#v:Go 字面量风格,main.User{ID:123, Name:"foo", Active:true}—— 可直接复制进测试代码;对nil切片或 map 明确输出nil,不会和空[]混淆
高频写文件必须套 bufio.Writer,否则性能崩得很快
每次调用 fmt.Fprintf 直接写 *os.File,等于每次触发一次系统 write 调用。小数据量看不出来,但每秒写几百行就明显卡顿甚至 IO wait 升高。
- 正确做法:用
bufio.NewWriter(file)包一层,再传给fmt.Fprintf - 别忘了最后调用
buf.Flush()或file.Close(),否则缓冲区里最后一段内容可能永远不落盘 - 错误示例:
fmt.Fprintf(file, "...")循环一百次 → 一百次系统调用;改成fmt.Fprintf(buf, "...")+ 一次buf.Flush()→ 实际可能只触发几次 write
补零、进制、对齐这些细节不注意,文件内容就难解析
生成编号、时间戳、协议字段时,宽度和填充规则必须显式写清楚,靠字符串拼接或条件判断反而更易出错。
-
%02d表示至少两位,不足补零;%2d是补空格,会导致字段长度不一致 - 负数要预留符号位:
%04d对-7输出-007,不是00-7 - 十六进制加前缀用
%#x,不是%#06x就能保证总宽 6——它包含0x,所以%#06x对255输出0x00ff(共 6 字符) -
%b、%x、%o只接受整数;传float64会 panic,别想当然
真正容易被忽略的是:写文件前没检查 os.Create 或 os.OpenFile 的 err,导致 fmt.Fprintf 对 nil *os.File 静默失败;还有就是忘记 \n,多条记录挤在同一行,肉眼根本分不清哪条是哪条。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











