Table of Contents
try-handler proposal" >try-handler proposal
示例和实践" >示例和实践
总结" >总结
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

Aug 04, 2023 pm 05:05 PM
go


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!

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

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to send Go WebSocket messages? How to send Go WebSocket messages? Jun 03, 2024 pm 04:53 PM

In Go, WebSocket messages can be sent using the gorilla/websocket package. Specific steps: Establish a WebSocket connection. Send a text message: Call WriteMessage(websocket.TextMessage,[]byte("Message")). Send a binary message: call WriteMessage(websocket.BinaryMessage,[]byte{1,2,3}).

In-depth understanding of Golang function life cycle and variable scope In-depth understanding of Golang function life cycle and variable scope Apr 19, 2024 am 11:42 AM

In Go, the function life cycle includes definition, loading, linking, initialization, calling and returning; variable scope is divided into function level and block level. Variables within a function are visible internally, while variables within a block are only visible within the block.

How to match timestamps using regular expressions in Go? How to match timestamps using regular expressions in Go? Jun 02, 2024 am 09:00 AM

In Go, you can use regular expressions to match timestamps: compile a regular expression string, such as the one used to match ISO8601 timestamps: ^\d{4}-\d{2}-\d{2}T \d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-][0-9]{2}:[0-9]{2})$ . Use the regexp.MatchString function to check if a string matches a regular expression.

The difference between Golang and Go language The difference between Golang and Go language May 31, 2024 pm 08:10 PM

Go and the Go language are different entities with different characteristics. Go (also known as Golang) is known for its concurrency, fast compilation speed, memory management, and cross-platform advantages. Disadvantages of the Go language include a less rich ecosystem than other languages, a stricter syntax, and a lack of dynamic typing.

How to avoid memory leaks in Golang technical performance optimization? How to avoid memory leaks in Golang technical performance optimization? Jun 04, 2024 pm 12:27 PM

Memory leaks can cause Go program memory to continuously increase by: closing resources that are no longer in use, such as files, network connections, and database connections. Use weak references to prevent memory leaks and target objects for garbage collection when they are no longer strongly referenced. Using go coroutine, the coroutine stack memory will be automatically released when exiting to avoid memory leaks.

How to view Golang function documentation in the IDE? How to view Golang function documentation in the IDE? Apr 18, 2024 pm 03:06 PM

View Go function documentation using the IDE: Hover the cursor over the function name. Press the hotkey (GoLand: Ctrl+Q; VSCode: After installing GoExtensionPack, F1 and select "Go:ShowDocumentation").

A guide to unit testing Go concurrent functions A guide to unit testing Go concurrent functions May 03, 2024 am 10:54 AM

Unit testing concurrent functions is critical as this helps ensure their correct behavior in a concurrent environment. Fundamental principles such as mutual exclusion, synchronization, and isolation must be considered when testing concurrent functions. Concurrent functions can be unit tested by simulating, testing race conditions, and verifying results.

Things to note when Golang functions receive map parameters Things to note when Golang functions receive map parameters Jun 04, 2024 am 10:31 AM

When passing a map to a function in Go, a copy will be created by default, and modifications to the copy will not affect the original map. If you need to modify the original map, you can pass it through a pointer. Empty maps need to be handled with care, because they are technically nil pointers, and passing an empty map to a function that expects a non-empty map will cause an error.

See all articles