在项目中用到了大量的goto语句,遭到了领导的指责,感觉挺委屈的。
作为一个程序员,在很多地方都看到说要避免goto语句的使用。goto语句如洪水猛兽,其实都误解了goto。滥用goto的确很恐怖,可是合理使用却能够对程序的结构性能有很大帮助。以下简单说一下项目中用到goto的3类地方。
1,多重循环嵌套。这是一个配置文件解析的例子,第一重循环读取文件一定长度的字符串,第二重循环判断读取的字符串是否包含行结束符。如果包含,提出一行,然后做处理,余下的字符放入另一个缓冲,下次再用;如果不包含,则再继续读文件。如果没有包含行结束符,需要跳到第一重循环处,由于现在在第二重循环,用break语句是不行的。可以设置一个局部变量标识是否独到行结束符,第二重循环结束后根据标识判断是否需要处理(读到完整一行需要另作处理)。由于另外引用了一个标识,代码其实更混乱了。这才二重循环了,如果多重循环呢,就要不断的声明临时变量。而用goto语句,这些临时变量都省略了。
2,函数出错处理。一个整数安装函数,首先要判断传入参数是否合理,其次参数证书,然后打开系统库,最后安装证书。任何一步出错都要释放前面所有的打开的资源,函数成功也要释放资源。如果不用goto,每一步出错的时候都要重新写一遍前面资源的释放语句。如果某天某个资源的释放函数变了,则每一处都要修改。程序员一般都很讨厌这种纯体力的修改,枯燥无味还很容易漏掉。有没有其他什么办法呢?答案是用goto语句。每一步失败,直接goto到函数收尾处,在收尾处根据资源是否申请成功(可根据是否null来判断),决定是否释放。所有的释放函数写到了一个地方,代码简练了很多,且容易维护。这种情况很容易出现,最早的时候,我也是不敢用goto,但是最终发现goto可以解决问题,为何不用?到现在我都大胆了。当然关于函数出错处理的资源释放可以用auto指针,相比最粗放的做法简练了很多,但是仍然没有goto来的简洁,效率也不够好。另外,对于不同资源的释放方式不同,就要写不同的auto指针类了。
3,模块的清晰划分。考虑一个安装证书的demo,第一步是安装根证书,第二步是安装证书,第三步是查找证书,第四步是验证证书,最后还要返回第一步让用户再次做选择。每一步根据用户的选项做处理,比如用户选择安装根证书,执行安装根证书功能,完成后进入安装证书部分,仍由用户做出选择。不用goto的话,首先要写一个while循环,因为要返回第一步,其次要写大量的if和else嵌套。而用了goto之后,每一功能可以用一个goto标签标识,执行完一步或者退出执行这一步只需要goto到下一个功能即可,代码简练了很多。
其实,不应该怕goto,他毕竟给了我们一种选择,优秀的程序员知道什么时候该用什么,不该用什么,掌握好goto的优缺点,做到心中有数,就不仅不怕,还会用的很爽。