hello,大家好,欢迎来到银之庭。我是Z,一个普通的程序员。
《大意没闪》系列是记录我工作中遇到的低级但常见的代码bug的系列文章,这是本系列的第一篇,主题是:在for循环中直接return。
1. bug示例
核心的bug伪代码如下所示,就像标题说的,在for循环中直接return了:
for item in items:
// do something
// ...
if item.isXxx:
return
如果for循环中的逻辑比较简单,这种bug还是比较容易看出来的,但如果for循环中的逻辑很复杂,比如达到了几十上百行,有各种业务逻辑判断时,我们就很容易陷入到单个元素的处理逻辑中,忘了我们处在一个for循环里,心里想着“如果这个元素是这样的,就应该直接返回,不用后续处理了“,然后写出上面的直接return的代码(没错,说的就是我)。
2. bug影响
这种bug会导致列表中后面的部分元素得不到执行,如果有一个Kafka consumer,它会批量拉取消息,然后用一个for循环执行,但for循环中有这个bug,这时候从业务上看起来就像consumer漏消息了一样(没错,我就是这个情况,线上出问题后最开始还没想到是代码的问题,以为是公司Kafka服务有问题,查了半天)。
3. 如何避免
说实话,这种bug属于如果你写的时候没注意,事后很难主动发现的bug。首先,code review几乎不可能发现,因为reviewer几乎不会看这么仔细,尤其是for循环内部逻辑很复杂的话,他也很容易陷入单一元素的处理逻辑中去;其次,代码扫描工具也几乎不会扫描这种问题,因为这实际上是个业务逻辑,有可能在for循环中直接return是符合逻辑的,所以代码扫描工具最多只会报个warn,但众所周知,程序员向来忽略warn;最后,这种bug上线后,即使线上出了问题,想要找到这个罪魁祸首,也会费一番力气,可能还得靠“灵光一闪“这种东西(没错,说的还是我)。
这种bug几乎只能依靠写代码的程序员提前意识到这个问题,在for循环中时刻注意continue
,break
和return
的使用来避免,而不是后期去发现。所以,我决定写这篇以及《大意没闪》这一系列文章,主要目的就是给我,以及所有看到这篇文章的同学提个醒,希望我们以后都不要再犯这样的错误了。