Hello everyone, I am fried fish.
Go's error handling has always been the most prominent place, and many students have put forward various proposals, such as: introducing try-catch, replacing if err != nil with panic, introducing new keywords, etc. But these were rejected one by one.
However, the community still hasn't given up. It was interesting to see a new proposal " proposal: runtime: add parameters to recover to only return specific types " over the weekend.
Today, Fried Fish will take you to learn together.
Syntax Description
Basic usage of Go's panic, recover, and defer. The following code:
package main
import "fmt"
func mayPanic() {
panic("a problem")
}
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered. Error:\n", r)
}
}()
mayPanic()
fmt.Println("After mayPanic()")
}
Output result:
Recovered. Error:
a problem
new proposal
Due to the Go1 compatibility guarantee, the new proposal is a minor operation on the original recover function. It is hoped that parameters can now be added to the recover at runtime, and only support specific types to be returned .
function signature:
recover(except ...interface{})
Case code:
defer func(){
if err := recover(&MyError{}, &HelloError{}); err != nil {
switch e := err.(type) {
case *MyError:
fmt.Println(e)
case *HelloError:
fmt.Println(e)
}
}
}
In the above code, the recover function only supports pointer types passed in MyError and HelloError. Then in the processing logic, according to the incoming error type, the assertion classification is performed, and in fact, different logic processing is performed.
The point is to limit the type of the recover input parameter.
discuss
Some friends may have found it. Compare the usage of PHP's try-catch. Is it similar to the previous proposal code?
The following code:
try {
...
}
catch (Exception $e) {
echo $e->getMessage();
}
catch (InvalidArgumentException $e) {
echo $e->getMessage();
}
catch (BarException $ex)
{
echo $e->getMessage();
}
catch (FooException $ex)
{
echo $e->getMessage();
}
Essentially this new proposal is a way to implement try-catch in Go without breaking Go1 compatibility.
When the community communicated, they also discovered that users can independently implement Go's try-catch-like pattern under the existing mechanism.
The following code:
func Recover(expect ...interface{}) interface{} {
if err := recover(); err != nil {
if len(expect) == 0 {
return err
}
rv1 := reflect.Indirect(reflect.ValueOf(err))
for _, e := range expect {
rv2 := reflect.Indirect(reflect.ValueOf(e))
if rv1.Type() == rv2.Type() {
return err
}
}
panic(err)
}
return nil
}
The problem with this homebrew method is that every Recover panic increases the stack depth by 2. Therefore, it is still hoped that Go officially supports it at runtime.
It also plays a role in the comparison of the use of the Go standard library. The codes involved are basically:
At least the following places in the standard library can be reused:
- text/template/exec.go
- go/parser/interface.go
- go/types/check.go
- go/ast/print.go
- encoding/json/encode.go
- encoding/gob/error.go
Summarize
This proposal essentially hopes to implement an error handling mechanism model similar to the Go version of try-catch by adding input parameter control to the recover function and cooperating with internal logic, and there is actually room for reuse in the Go standard library.
But at this stage, the proposal is also mixed for and against, and some people think that users can implement it themselves, so there is no need to increase the complexity and do this realization that the benefits are not large enough.
Do you think this would fix some of the mechanical flaws in Go's error handling?
The article is updated continuously, you can read it by searching on WeChat [Brain fried fish]. This article has been included in GitHub github.com/eddycjy/blog . If you are learning Go language, you can see the Go learning map and route . Welcome to Star to urge you to update.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。