
fmt.Printf 常见占位符怎么选,别硬背
Go 的 fmt.Printf 占位符不是越多越好,关键是匹配变量类型和输出意图。比如用 %d 打印 float64 会 panic,用 %s 打印结构体默认只输出类型名,不是字段内容。
实操建议:
-
%v最安全:自动推导类型,适合调试,但对浮点数可能精度过高(如3.141592653589793) -
%+v看结构体字段名:打印struct{X int}时输出{X:42},比%v多一层可读性 -
%#v输出 Go 语法格式:适合生成可复用的字面量,比如map[string]int{"a": 1} - 整数优先用
%d,十六进制用%x(小写)或%X(大写),地址用%p,别混用
字符串和数字格式控制容易漏掉的参数
光靠占位符不够,宽度、精度、对齐这些修饰符才是控制输出的关键。比如 %6.2f 表示总宽至少 6 字符、小数点后 2 位;%06d 表示不足 6 位时前面补 0。
常见错误现象:
立即学习“go语言免费学习笔记(深入)”;
- 用
%.2f格式化整数(如42)会报错:fmt.Printf: %f verb not allowed for integer -
%8s对短字符串右对齐,但想左对齐得写成%-8s,少个负号就错位 - 精度对字符串是截断长度(
%.3s→"hel"),对浮点数才是小数位数,语义完全不同 - 用
%q打印字符串会加双引号并转义("hello\n"),适合日志或调试,但不适合用户界面
fmt.Printf 和 fmt.Sprint 系列函数的区别在哪
不是所有场景都该用 fmt.Printf。它直接写到 os.Stdout,没法捕获结果;而 fmt.Sprintf 返回字符串,适合拼接、缓存或传给其他函数。
使用场景判断:
- 要打印到终端/日志:用
fmt.Printf或fmt.Println - 要构造 SQL、HTTP header、JSON key 等字符串:必须用
fmt.Sprintf,否则得先写文件再读回来 - 性能敏感循环里频繁调用
fmt.Sprintf会分配内存,可考虑strings.Builder+fmt.Fprint -
fmt.Print不解析占位符,fmt.Printf("name=%s", name)是标准写法,别写成fmt.Print("name=", name)—— 后者在并发日志中容易错乱
自定义类型怎么让 fmt.Printf 按自己想要的方式输出
默认情况下,自定义 struct 或 type 别名走 %v 的通用逻辑,往往不直观。想控制输出,就得实现 fmt.Stringer 接口。
实操要点:
- 只需实现一个方法:
func (t MyType) String() string,返回想要的字符串 - 注意不要在
String()里再调用fmt.Sprintf打印自身,否则递归 panic - 如果只想影响
%v,用Stringer就够了;如果还要区分%#v、%q等,得实现更底层的fmt.Formatter接口 - 第三方库类型(如
time.Time)已经实现了String(),所以fmt.Printf("%v", time.Now())输出可读时间,不是内存地址
占位符本身没玄学,但类型匹配、修饰符组合、接口实现这三块最容易出 silent bug —— 尤其是跨包传递自定义类型时,别人调你的函数却看到一串 {main.MyStruct},问题往往不在 printf,而在忘了加 String() 方法。










