Home > Backend Development > Golang > Go try Is the new proposal reliable? Want to simplify error handling

Go try Is the new proposal reliable? Want to simplify error handling

Release: 2023-08-04 17:05:37
forward
1285 people have browsed it


In the recent new try proposal "proposal: Go 2: error handling: try statement with handler[1]》has sparked heated discussions in the community, let’s fight the community again! ! !

Today Jianyu will open it with everyone to see if this can open up and reorganize the Go error handling mechanism.

Background

The proposal author @Greg Weber from PingCAP will do this based on two factors, one is in the "Go Developer Survey 2022 Q2 Results[2]" is clearly mentioned.

Go try Is the new proposal reliable? Want to simplify error handling

With the release of Go1.18 generics, the original most contradictory generics have received a preliminary solution. According to community surveys, the biggest challenge faced by developers when using Go has shifted to error handling, and energy needs to be invested to "solve" it.

Another factor is that it is well known that Go error handling code is relatively cumbersome. Engineers often joke that 30% of a Go project has if err = nil.

The following code:

_, err := f()
if err != nil {
    ...
}
_, err = r()
if err != nil {
    ...
}
_, err = w()
if err != nil {
    ...
}
Copy after login

I hope to make it more elegant. Many friends also agree with this design. It is indeed a simple and intuitive processing, which has formed a struggle in the community.

try-handler proposal

The solution mentioned in this proposal is to add a new statement try to achieve concise error handling. Make the processing of if err != nil smooth.

The following code:

try err, handler
Copy after login

The code generated after translation by the compiler:

if err != nil {
    return handler(err)
}
Copy after login

In the function, it can be as follows:

func(args...) (rtype1, rtypes..., rtypeN, error) {
    try err, handler
    ...
}
Copy after login

The code generated after translation:

func(args...) (rtype1, rtypes..., rtypeN, error) {
    if err != nil {
            return Zero(rtype1), Zeros(rtypes...)..., Zero(rtypeN), handler(err)
    }
    ...
}
Copy after login

It can also be processed only if err != nil. The following code:

try err
Copy after login

The translated code:

if err != nil {
    return err
}
Copy after login

will not call the non-existent handler for processing, and will return directly. Three lines (if err != nil logic) directly change 3 words (try).

If you don’t want to write a function, you can also directly:

x, err := f()
try err, fmt.Errorf("f fail: %w", err)
Copy after login

The scenario for defer try can be as follows:

func CopyFile(src, dst string) error {
    defer try func(err error) error {
        return fmt.Errorf("copy %s %s: %w", src, dst, err)
    }
    ...
}
Copy after login

The input parameters are more flexible, and the author hopes that it will be generic. This can adapt to the requirements of various scenarios.

示例和实践

针对本提案,原作者给出了各类使用场景的示例。如下代码:

import (
    "fmt"
)

// This helper should be defined in the fmt package
func Handlew(format string, args ...any) func(error) error {
 return func(err error) error {
  args = append(args, err)
  return fmt.Errorf(format+": %w", args...)
 }
}

// This helper should be defined in the fmt package
func Handlef(format string, args ...any) func(error) error {
 return func(err error) error {
  args = append(args, err)
  return fmt.Errorf(format+": %v", args...)
 }
}

func valAndError() (int, error) {
    return 1, fmt.Errorf("make error")
}

func newGo() (int, error) {
    x, err := valAndError()
    try err

    // Common formatting functions will already be provided
    i := 2
    x, err = valAndError()
    try err, Handlew("custom Error %d", i)

    // Using a custom error type
    // For convenience the error type can expose a method to set the error
    x, err = valAndError()
    try err, TheErrorAsHandler(i)
}

type TheError struct{
    num int
    err error
}

func (t TheError) Error() String {
    return fmt.Sprintf("theError %d %v", t.num, t.err)
}

func TheErrorAsHandler(num int) func(err) TheError {
    return func(err error) TheError {
        return theError{ num: i, err: err }
    }
}
Copy after login

另外在日常的 Go 工程中,提案作者认为 CopyFile 函数是新提案语句的一种很好的实践。为此基于 try-handler 进行了一版改造和说明。

如下代码:

// This helper can be used with defer
func handle(err *error, handler func(err error) error) {
    if err == nil {
        return nil
    }
    *err = handler(err)
}

func CopyFile(src, dst string) (err error) {
    defer handle(&err, func(err error) error {
        return fmt.Errorf("copy %s %s: %w", src, dst, err)
    })

    r, err := os.Open(src)
    try err
    defer r.Close()

    w, err := os.Create(dst)
    try err, func(err error) error {
            os.Remove(dst) // only if Create fails
            return fmt.Errorf("dir %s: %w", dst, err)
    }
    defer w.Close()

    err = io.Copy(w, r)
    try err
    err = w.Close()
    try err
    return nil
}
Copy after login

引入 try-hanlder 后,能够做到:

  • 插入错误的返回语句,进行机制预设。
  • 在返回错误之前将错误处理函数组合在一起,便于后续的处理。

总结

在这个新提案中,一旦实施,就可以减少如下代码的编写:

if err != nil {
  return ...
}
Copy after login

在代码编写上会节省一些行数,且可以为错误处理机制引入一些新的 ”操作“,这是该提案的优势。

但是从 Go 开发者的角度而言,会引入一些新的副作用,例如:初学者的学习成本、Go 工具链的改造、程序理解的复杂度增加。

另外新的语句,似乎比较难与 Go1.13 引入的 error.Is 和 As 有较好的相关联性。如果是做一个第三方用户库引入倒可以,但若是作为标准进入 Go 源代码中,似乎又有些格格不入(提案作者希望进入)。

看了那么多提案,Go 错误处理机制的 ”升级“,似乎陷入了手心手背都是肉的阶段...

The above is the detailed content of Go try Is the new proposal reliable? Want to simplify error handling. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
go
source:Golang菜鸟
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template