golang fmt.Sprintf 中 %d 与 %s 混用会怎样

更新日期: 2022-06-10 阅读次数: 2610 字数: 340 分类: golang

写了一个后台分页的 bug,问题的原因在 fmt.Sprintf 中我将 int 类型传递给了 %s。

有问题的代码

categoryId := 5

if categoryId > 0 {
	url += fmt.Sprintf("?category=%s", categoryId)
}

其输出是:

/solutions?category=%!s(int=5)

导致之后的参数解析逻辑没有正常执行。

而且这个 bug 具有隐蔽性,从打印日志输出看,我看了半天也没有发现这是一个错误的输出。 后来看 golang fmt 的文档,才知道这是错误信息。

Format errors: If an invalid argument is given for a verb, such as providing a string to %d, the generated string will contain a description of the problem, as in these examples: All errors begin with the string "%!" followed sometimes by a single character (the verb) and end with a parenthesized description.

正确的代码

categoryId := 5

if categoryId > 0 {
	url += fmt.Sprintf("?category=%d", categoryId)
}

输出:

/solutions?category=5

这才一切运行正常。

隐蔽的 bug

我一直以为 %s %d 是可以混用的,可能是用 python 时养成的坏习惯。

而 golang 拒绝一切隐式转换,所以就出现了错误信息。 最危险的时,这并没有引起运行时错误,也没有编译时错误,非常难发现。

这时单元测试就非常有必要了。

规避方法

  • 单元测试
  • go vet 检测

参考

  • https://pkg.go.dev/fmt

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式