最快方式是手写 if 语句(约28 ns/op,零分配),其次为 strconv.FormatBool(35 ns/op,零分配),fmt.Sprintf("%t", b) 最慢(95 ns/op,每次约2次堆分配)。

用 fmt.Sprintf 转换最直观,但不是最快的
多数人第一反应是 fmt.Sprintf("%t", b),它确实能正确输出 "true" 或 "false",也支持多种格式(如 %v、%s 配合类型断言)。但 fmt 包做了大量通用格式解析和内存分配,对高频场景(比如日志字段拼接、序列化循环体)会有明显开销。
实操建议:
- 仅在调试、低频或需要格式组合(如
"flag="+fmt.Sprintf("%t", b))时用fmt.Sprintf - 避免在 tight loop 里调用,尤其当布尔值数量大且稳定(如结构体批量转 JSON 前预处理)
-
fmt.Sprint(b)比fmt.Sprintf("%t", b)略快一点,因为省了格式解析,但仍有反射和分配成本
手写三元表达式是零分配、最快的方式
Go 编译器对简单三元逻辑(b ? "true" : "false")优化极好,生成的汇编不涉及堆分配、无函数调用,字符串字面量直接进只读段。这是生产环境高吞吐服务(如 API 网关字段序列化)的首选。
示例:
立即学习“go语言免费学习笔记(深入)”;
func boolToString(b bool) string {
if b {
return "true"
}
return "false"
}
// 或更紧凑:
// return map[bool]string{true: "true", false: "false"}[b]
// 但注意:map 查找有哈希开销,不如 if 快
注意事项:
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 必须返回字面量字符串(
"true"/"false"),不要拼接或调用string() - 如果需大小写变体(如
"TRUE"),仍可用同样模式,但要确保所有分支都返回字面量 - 不能用于需要接口兼容的泛型上下文(比如
fmt.Stringer),这时得另做封装
用 strconv.FormatBool 是标准库推荐,平衡可读与性能
strconv.FormatBool 是标准库专为此设计的函数:内部用 if 分支 + 字面量,无反射、无 fmt 解析、无额外分配,语义清晰,且被广泛测试过边界情况(如 race、nil 指针不影响它,因为它只收 bool 值)。
对比实测(10M 次):
-
strconv.FormatBool(b):约 35 ns/op,零分配 -
fmt.Sprintf("%t", b):约 95 ns/op,每次 ~2 次堆分配 - 手写 if:约 28 ns/op,零分配 —— 快但多写几行
所以实际选型逻辑很直接:
- 追求极致性能且控制代码路径 → 手写 if
- 看重可维护性、团队一致性、不想造轮子 → 无条件用
strconv.FormatBool - 已有
fmt依赖且调用不频繁 → 可继续用,不必强改
警惕字符串拼接时的隐式转换陷阱
常见错误是把布尔值直接塞进 + 表达式:"status:" + b —— 这会编译失败,因为 Go 不支持 string 和 bool 直接相加。有人会绕成 "status:" + fmt.Sprintf("%t", b),结果在热点路径引入意外分配。
正确姿势:
- 用
fmt.Sprintf("status:%t", b)(单次格式化,比拼接快) - 或提前转好再拼:
s := strconv.FormatBool(b); result := "status:" + s - 若在
log.Printf类场景,直接传参:log.Printf("status: %t", b),让fmt内部处理,避免中间字符串
真正容易被忽略的是:只要布尔值参与字符串构建,就要主动决定转换时机——延迟到最终输出前,还是提前固化为字符串。前者省内存但可能重复计算,后者占一点内存但确定高效。没有银弹,得看它出现在日志、HTTP 响应体,还是数据库查询参数里。

















