Go fmt占位符应按类型分组记忆:通用%v/%+v/%#v区别在详细程度;数字%d/%x/%f/%e须对号入座;字符串%s/%q/%x注意nil和编码;修饰符宽度精度需规范组合,避免panic。

Go 的 fmt 包占位符不是“记不住”,而是没理清分类逻辑——按类型分组记忆,比死背 %v %d %s 有效得多。
基础通用占位符:%v、%+v、%#v 怎么选?
这三个是调试和日志最常用的,区别不在“输出什么”,而在“输出多详细”:
-
%v:默认格式,结构体只输出字段值,不带字段名 -
%+v:带字段名,适合快速定位结构体内容,比如fmt.Printf("%+v", struct{A int; B string}{1, "x"}) // {A:1 B:"x"} -
%#v:输出 Go 语法可复现的字面量形式,含类型信息,适合生成测试数据或反射调试
注意:%v 对 nil 接口、nil 切片等输出 ,但不会 panic;而 %s 遇到 nil []byte 会 panic。
数字类型必须对号入座:%d、%x、%f、%e 各管什么?
整数、浮点、十六进制不能混用,否则结果错乱或 panic:
立即学习“go语言免费学习笔记(深入)”;
-
%d:有符号十进制整数(int,int8等),uint类型也兼容 -
%x:小写十六进制(0xff),%X是大写(0xFF);只接受整数,传float64会 panic -
%f:十进制浮点,如123.450000;默认 6 位小数,可用%.2f控制精度 -
%e或%E:科学计数法,%e输出1.234500e+02,%E是1.234500E+02
特别注意:%d 对 float64(3.14) 会截断为 3,但这是隐式转换,不报错;而 %f 对 int(5) 会自动转成 5.000000,Go 允许这种宽泛匹配。
字符串与字节切片:%s、%q、%x 容易踩的坑
%s 看似简单,实则边界敏感:
-
%s:要求参数是string或[]byte;传nil []byte会 panic,但nil string是合法的(输出空字符串) -
%q:加双引号 + 转义,适合日志中安全输出用户输入,比如fmt.Printf("%q", "a\nb") // "a\nb" -
%x对[]byte或string输出十六进制字符串(无空格),% x(中间有空格)才加空格分隔
别用 %s 打印非 UTF-8 字节序列——它不会报错,但可能输出乱码或截断;需要原始字节请用 %x 或 %q。
宽度、精度、标志位这些修饰符怎么组合?
修饰符不是可选技巧,而是控制输出一致性的刚需,尤其在对齐日志或生成固定宽表格时:
- 宽度(如
%5d):右对齐,不足补空格;%-5d左对齐 - 精度(如
%.2f):对浮点是小数位数,对字符串是最大输出长度(%.3s截取前 3 字符) -
%06d:数字补零对齐,42→000042;但%06s无效(字符串不补零) -
%+d:强制显示正负号,+42;% d(空格)对正数加空格、负数加负号,用于对齐正负输出
组合示例:
fmt.Printf("|%6.2f|%6s|\n", 3.14159, "hi") // | 3.14| hi|。注意:宽度和精度顺序不能颠倒,%.2f 合法,.2%f 语法错误。
真正难的不是记住所有占位符,而是理解哪些组合在 runtime 会 panic、哪些只是静默截断、哪些依赖参数实际类型——比如 %d 接 uintptr 在 32 位系统和 64 位系统行为不同,%v 却始终安全。线上服务里,宁可用 %v 或显式类型转换,也别赌隐式行为。










