Если вы используете C ++, просто используйте исключения. Если вы используете C, первый стиль отлично работает. Но если вам действительно нужен второй стиль, просто используйте gotos - это именно тот тип ситуации, когда gotos действительно является самой ясной конструкцией.
int errorCode = 0;
if ((errorCode = doSomething()) != 0) goto errorHandler;
if ((errorCode = doSomethingElse()) != 0) goto errorHandler;
...
if ((errorCode = doSomethingElseNew()) != 0) goto errorHandler;
return;
errorHandler:
// handle error
Да, gotos может быть плохим, и исключения или явная обработка ошибок после каждого вызова могут быть лучше, но gotos гораздо лучше, чем использовать другую конструкцию, чтобы попытаться плохо имитировать их. Использование gotos также упрощает добавление другого обработчика ошибок для конкретной ошибки:
int errorCode = 0;
if ((errorCode = doSomething()) != 0) goto errorHandler;
if ((errorCode = doSomethingElse()) != 0) goto errorHandler;
...
if ((errorCode = doSomethingElseNew()) != 0) goto errorHandlerSomethingElseNew;
return;
errorHandler:
// handle error
return;
errorHandlerSomethingElseNew:
// handle error
return;
Или, если обработка ошибок - это больше разновидность «раскручивания / очистки того, что вы сделали», вы можете структурировать ее следующим образом:
int errorCode = 0;
if ((errorCode = doSomething()) != 0) goto errorHandler;
if ((errorCode = doSomethingElse()) != 0) goto errorHandler1;
...
if ((errorCode = doSomethingElseNew()) != 0) goto errorHandler2;
errorHandler2:
// clean up after doSomethingElseNew
errorHandler1:
// clean up after doSomethingElse
errorHandler:
// clean up after doSomething
return errorCode;
Эта идиома дает вам преимущество, не повторяя код очистки (конечно, если вы используете C ++, RAII будет охватывать код очистки еще более чисто.