Why does Go not have Try-Catch?
Go intentionally does not support try-catch, and only supports panic-recover syntax. This incurs the resentment of numerous developers who are accustomed to error handling using try-catch. Then, what is the reason for not including try-catch? It is because try-catch has several problems.
try-catch-finally
The try-catch statement is a statement for handling error situations and exceptional situations that may occur during program execution (runtime). Also, the finally statement writes code that must be executed unconditionally regardless of whether an exception occurs.
Error Handling and Responsibility
In the 1980s and 1990s, error handling was very simple. The error messages were just 'Floppy disk full', 'No floppy disk in drive', and 'No write permission for floppy disk', and developers of that time threw the error to the error handling point and handled it in common when an error occurred. In this situation, the try-catch statement worked efficiently.
However, as time passed, the situation changed. Business logic became complex, databases and transactions emerged, numerous API calls were made through networks, numerous request messages had to be parsed, and even with the advent of concurrent programming, errors had to be handled in threads other than the main thread.
Errors became so complex that they could no longer be handled in one place, and no single place could be responsible for all errors. This is where a serious problem arises with try-catch.
Shifting Responsibility with try-catch
In short, try-catch is a method for the entity that caused the error to pass on the responsibility (cleanup) for the error occurrence to someone else. The target of the postponement could be a catch statement, its parent method, or someone in its parent's parent's parent's parent... In other words, in a world where error handling is increasing and becoming more complex, the method try-catch has chosen is 'someone will do it'. Let's look at the code below.
1try {
2 data = readFile("hello.txt");
3 structuredData = parseData(data);
4 insertDBStatus(structuredData[1]);
5 startHTTPServer(structuredData[2]);
6} catch (Exception e) {
7 e.printStackTrace();
8}
The problem with the code above is that it is unclear who is handling the printStackTrace, and it is not possible to know which code caused the error. Even worse, the problem becomes more terrible as more logic is created within the try statement. However, paradoxically, as development becomes more complex, developers have become addicted to try-catch statements that shift responsibility, do not think about error handling, have weakened responsibility, and eventually forget about the essence of error and exception handling. So how did golang solve this problem?
panic, recover
One of the advantages of Go is that it has several systems to make developers good developers without leading them down the wrong path. Panic-recover can also be cited as an example.
At first glance, panic and recover do not seem to be different from try-catch, but they are different in that they do not shift responsibility to the outside when a problem occurs. When a panic occurs in go, it is necessary to resolve it at the location where the panic occurred rather than turning the value to the outside. This assigns responsibility for error handling to the developer, inducing them to consider more deeply where, who, and how to handle the error. It guarantees autonomy for the user, while leaving room for thought.
Also, the selection of the word panic is very excellent. Unlike try-recover, panic-recover, just by the words themselves, puts pressure on developers that it should only be used in clear error situations, not exceptional situations. Naturally, developers do not overuse recover and use it only where necessary. This is very helpful in writing concise code in Go.