Use cases for goto

tags: programming

This article is a response to all my university professors who, for some reason, think goto is useless and should be avoided at all costs.

Some use cases

The most important use case there is for goto is by far error handling when there are more than 1 points of failure. In this case, you might want to cleanup some resources while also skipping part of the code that should not be executed, without having to deal with flags, helper functions, and other methods that would make the code ugly, slower and error prone. Try rewriting the following snippet without a goto:

int
foo(int *bar, int *baz)
{
	if (!func1())
		goto fail;
	if (!func2())
		goto fail;
	if (!func3())
		goto fail;

	return 0;

fail:
	warn("foo failed");
	if (bar != NULL)
		free(bar);
	if (baz != NULL)
		free(baz);

	return -1
}

Another use case is breaking out of deeply nested code. Let’s say you’ve got 3 for loops and there’s a special case in which you really want to break out of all the loops at once. how do you do that? There are multiple ways you can go about doing so but one way would be to set a flag and check it on every nested level.

flag = 0;

for (i = 0; i < 10; i++) {
	for (j = 0; j < 10; j++) {
		for (k = 0; k < 10; k++) {
			...
			if (flag)
				break;
		}
		if (flag)
			break;
	}
	if (flag)
		break;
}

Another ugly hack you can use is something another colleague from university showed me, and something I would never use; when the flag is set, manually max out all the loop counters.

A pretty straight-forward solution would also be to put the loop into a function and use a return statement to break out of all the loops. That’s actually a good solution, and I’m aware of it, but I want to provide another solution, which is also quite faster than using a function since it avoids that additional function call.

An alternative, and in my opinion, better way of solving this problem would be by using a (don’t say it, don’t say it) goto:

flag = 0;

for (i = 0; i < 10; i++) {
	for (j = 0; j < 10; j++) {
		for (k = 0; k < 10; k++) {
			...
			if (flag)
				goto end;
		}
	}
}
end:
...

Who cares, anyway?

In the first use case, the code is much more readable and you avoid code duplication. In the second use case the goto solution actually does improve performance. The reason why is simple; we check for flag on every single loop, which means, that in case flag is never set, we’ll have done 10 * 10 * 10 = 1000 checks just to see if flag is set. And that’s just with 3 for loops going from 0 to 10 each; think how easily this can scale up if you just increase the iterations. The goto solution does only one check in the third loop, which means that, in the above scenario, where flag never gets set, we’ll have done only 10 checks - that’s 100 times faster than the other solution.

Using a function is almost just as fast as using a goto without a function, but not having to call a function is generally faster. Both solutions are great and totally valid, I just want to show an alternative one.

Final note

goto does have its place but it should be used carefuly; if you overuse it, your code will either become incomprehensible, or flat out broken. The use cases I showcased in this post are very common and sometimes the code can be vastly improved with just a simple goto if used correctly.

Again, thanks to both my colleagues who helped me improve this article with their recommendations.