为goto正名
来源:互联网 发布:淘宝头条号赚钱么 编辑:程序博客网 时间:2024/05/30 04:20
昨天和老板一块儿review我的code,当看到我的代码中存在一些goto语句的时候,老板条件反射般严肃的问我:“为什么要用goto语句”?
我很理解她为什么会惊讶。自从计算机科学一代宗师Dijkstra于1968年发表了著名的文章《Go To Statement Considered Harmful》之后,goto语句就成了过街老鼠,人人喊打。甚至有人开玩笑说:“今天你敢用goto,明天老板就让你go home”。
“不要在程序中使用goto”已经成为绝大多数开发者的圣经,但却很少有人认真的思考过,为什么会这样?
goto问题之所以这么臭名昭著,从历史的角度来看,在Dijkstra在ACM发表那篇文章之前,现代软件构造方法还没有出现,goto语句是当时实现流程控制的主要手段。那篇文章发表之后,引发了大量的争论,并最终导致了当代程序员认为理所当然的结构化编程的出现与风靡。
但有趣的地方也正在与此,结构化编程是由goto问题的争论产生的。从时间的顺序上讲,结构化编程语言Pascal,C及现代面向对象语言C++,Java,C#均出现在1968年之后,但为什么这些语言都保留了goto或与goto功能相近的语句?
所以,问题本身并不在于goto。Dijkstra之所以竭力反对goto的原因是因为泛滥的使用goto将会导致软件难以理解和跟踪。所以,我们要反对的是“难以理解和跟踪”的程序,而不是goto语句。
goto语句一定会造成程序“难以理解和跟踪”吗?不!恰恰相反,在适当的地方适当的使用goto恰恰可以让程序更加容易的理解和跟踪,甚至让代码更有效率。举个例子:
while(1) {
...
do {
...
for(i=0; i < max; i++) {
if(a[i] == 10)
goto done;
else
count += a[i];
}
...
} while( n > 0);
...
}
done:
...
由于break只能跳出一级循环,在很深的循环嵌套中,如果存在一个从结束所有循环的需求,则goto是最能直接体现此意图,并让程序更简捷的手段。否则上面的代码不得不写为:
boolean finished = false;
while(1) {
...
do {
...
for(int i=0; i < max; i++) {
if(a[i] == 10) {
finished = true;
break;
}
else
count += a[i];
}
if(finished)
break;
...
} while( n > 0);
if(finished)
break;
...
}
再看另外一个例子:
#define FREE(p) if(p) { /
free(p); /
p = NULL; /
}
void foo()
{
char *fname=NULL, *lname=NULL, *mname=NULL;
fname = ( char* ) calloc ( 20, sizeof(char) );
if ( fname == NULL ){
goto ErrHandle;
}
lname = ( char* ) calloc ( 20, sizeof(char) );
if ( lname == NULL ){
goto ErrHandle;
}
mname = ( char* ) calloc ( 20, sizeof(char) );
if ( mname == NULL ){
goto ErrHandle;
}
......
ErrHandle:
FREE(fname);
FREE(lname);
FREE(mname);
ReportError(ERR_NO_MEMOEY);
}
在这种情况下,goto语句会让你的程序更易读,更容易维护。
还有其它良好使用goto的例子,这里就不一一列举了。
孔子曰:“过犹不及”。教条主义般的反对goto,其原因和结果都只能是本末倒置。我们的核心思想是:构造易于阅读和理解的代码。只要抓住这一点,我们就能以平常心看待goto。不使用goto,仍然可以写出非常糟糕的代码;而使用了goto语句的程序,却很有可能是优秀的代码。事实上,goto和其它语句及机制一样,都只不过是为我们这个核心思想服务的手段或工具罢了。
自从1968年,goto语句就背负了它不该承受的恶名。到了为其平反的时候了。
- 为goto正名
- 为Linux正名!
- 为兔子正名!
- 为Linux正名!
- 为搜索引擎优化正名
- 为Indy的TIdHashMessageDigest正名
- 为PPT架构师正名
- 为“存在即是合理”正名
- 为FLASH正名!HTML5前景分析
- 为 HTC 的 Android 手机正名
- 为FLASH正名!HTML5前景分析
- 替“我坦白”正名为“我表白”
- IBM借Power6微处理器为频率地位正名
- 为Google Adsense正名,再坏也比百度联盟强!
- “父亲节”为程序员正名:谁说程序员不会表达爱?
- 数组之小传,为一维数组“正名”。
- 黑马程序员:为苹果与iOS开发者的前景正名
- 为自增(++)自减(--)运算符正名
- C# 事件机制
- 域之间的信任关系配置(英文)
- 启用 WebLogic Server 域之间的信任
- 请开发人员支持自动化测试
- 什么是诉和诉的要素——兼建立中国诉讼法理论体系
- 为goto正名
- 无助的悲凉
- CA认证原理
- mock.VerifyAll()? NO!
- soapUI快速入门[翻译]
- protel相关资料
- Disable or Ban PING in LinkSys
- 在Struts 2.0中国际化(i18n)您的应用程序
- C#: Reflection