这个 goto 有表达力吗?
以下代码是消息批处理例程的概念证明。我是否像瘟疫一样避免 goto
并重写这段代码?或者您认为 goto
是完成此任务的一种富有表现力的方式吗?
如果您要重写,请发布一些代码...
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
HaveAnotherMessage:
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
{
goto HaveAnotherMessage;
}
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
// queue processing code
}
The following code was a proof of concept for a message batching routine. Do I avoid goto
like the plague and rewrite this code? Or do you think the goto
is an expressive way to get this done?
If you'd rewrite please post some code...
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
HaveAnotherMessage:
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
{
goto HaveAnotherMessage;
}
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
// queue processing code
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
几乎总结了我对“goto”的想法。
由于多种原因,Goto 是一种糟糕的编程习惯。其中最主要的是几乎从来没有理由。有人发布了一个
do..while
循环,请使用它。使用布尔值
来检查是否应该继续。使用 while 循环。 Goto 是针对解释性语言的,并且是对汇编程序时代的回顾(JMP
有人吗?)。您使用高级语言是有原因的。这样您和其他人就不会在查看代码时迷失方向。为了使这个答案保持最新状态,我想指出
goto
和支撑错误的组合导致了 iOS 和 OS X 中的主要 SSL 错误。Pretty much sums up my thoughts on "goto."
Goto is bad programming practice for many reasons. Chief among them is that there is almost never a reason for it. Someone posted a
do..while
loop, use that. Use aboolean
to check if you should continue. Use a while loop. Goto's are for interpreted languages and a call back to assembler days (JMP
anyone?). You're using a high level language for a reason. So that you and everyone else doesn't look at your code and get lost.To keep this answer somewhat current I'd like to point out that a combination of
goto
and bracing errors caused a major SSL bug in iOS and OS X.如果您不想要现在拥有的“总是运行一次”功能,请将 goto 替换为 do-while 或简单的 while 循环。
Replace the goto with a do-while, or simply a while loop if you don't want the "always run once" functionality you have right now.
在这种情况下,摆脱 GOTO 是如此的容易,这让我哭了:
It's so amazingly easy to rid yourself of GOTO in this situation it makes me cry:
我想 goto 直观上更具可读性......但如果你想避免它,我认为你所要做的就是将代码放入
while(true)
循环中,然后循环末尾的break
语句用于正常迭代。并且goto
可以替换为continue
语句。最终,您只需学习读写循环和其他控制流结构,而不是使用 goto 语句,至少根据我的经验。
I guess the goto is SLIGHTLY more readable intuitively... But if you WANTED to avoid it I think all you'd have to do is throw the code in a
while(true)
loop, and then have abreak
statement at the end of the loop for a normal iteration. And thegoto
could be replaced with acontinue
statement.Eventually you just learn to read and write loops and other control flow structures instead of using
goto
statements, at least in my experience.有点与 Josh K 的帖子相关,但我在这里写它,因为评论不允许使用代码。
我能想到一个很好的理由:在遍历一些 n 维构造来查找某些东西时。 n=3 的示例 //...
我知道您可以使用“n”while 和布尔值来查看是否应该继续..或者您可以创建一个函数,将 n 维数组映射到一维并仅使用一维虽然但我相信嵌套的可读性要强得多。
顺便说一句,我并不是说我们都应该使用 goto,但在这种特定情况下我会按照我刚才提到的方式来做。
Kind of related to Josh K post but I'm writing it here since comments doesn't allow code.
I can think of a good reason: While traversing some n-dimensional construct to find something. Example for n=3 //...
I know you can use "n" whiles and booleans to see if you should continue.. or you can create a function that maps that n-dimensional array to just one dimension and just use one while but i believe that the nested for its far more readable.
By the way I'm not saying we should all use gotos but in this specific situation i would do it the way i just mentioned.
你可以重构为这样的东西。
You could refactor is to something like this.
嗯,我不太确定你想跳出 try 块。我很确定这不是一件安全的事情,尽管我对此不是 100% 确定。这看起来不太安全......
Umm, I'm not really sure you want to goto out of a try block. I'm pretty sure that is not a safe thing to do, though I'm not 100% sure on that. That just doesn't look very safe...
将“HaveAnotherMessage”包装到一个接收缓冲区的方法中,并且可以递归地调用自身。这似乎是解决此问题的最简单方法。
Wrap the "HaveAnotherMessage" into a method that takes in the buffer and may call itself recursively. That would seem to be the easiest way to fix this.
在这种情况下我会避免 goto 并重构它。我认为该方法读起来太长了。
I would avoid goto in this case, and refactor it. The method reads too long in my opinion.
我觉得你的方法太大了。它混合了不同级别的抽象,例如错误处理、消息检索和消息处理。
如果你用不同的方法重构它,
goto
自然会消失(注意:我假设你的主要方法称为Process
):I think your method is too big. It mixes different levels of abstraction, like error processing, message retrieval and message processing.
If you refactor it in different methods, the
goto
naturally goes away (note: I assume your main method is calledProcess
):