自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go try 新提案靠譜嗎?想簡化錯誤處理了

開發(fā) 前端
隨著 Go1.18 泛型的發(fā)布,原先矛盾最深的泛型已經(jīng)得到一個初步的解決方案。在社區(qū)調(diào)研上,開發(fā)者在使用 Go 時面臨的最大挑戰(zhàn)已經(jīng)轉(zhuǎn)移到了錯誤處理上,需要投入精力去 “解決” 它。

大家好,我是煎魚。

今天煎魚和大家一起打開來看看,這能把 Go 錯誤處理機(jī)制給掀開重整不。

背景

來自 PingCAP 的提案作者 @Greg Weber 會干這事基于兩個因素,一個是在《Go Developer Survey 2022 Q2 Results[2]》中明確提到。

圖片

隨著 Go1.18 泛型的發(fā)布,原先矛盾最深的泛型已經(jīng)得到一個初步的解決方案。在社區(qū)調(diào)研上,開發(fā)者在使用 Go 時面臨的最大挑戰(zhàn)已經(jīng)轉(zhuǎn)移到了錯誤處理上,需要投入精力去 “解決” 它。

另外一個因素就是眾所皆知的,Go 錯誤處理代碼比較繁瑣,常被工程師們戲稱一個 Go 工程里有 30% 都 if err = nil。

如下代碼:

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

希望讓其更優(yōu)雅。也有許多小伙伴認(rèn)同這個設(shè)計(jì),確實(shí)是簡單、直觀的處理,在社區(qū)形成了角力。

try-handler 提案

本次提案中所提到的解決方案,是增加一個新語句 try ,以此達(dá)到簡潔的錯誤處理的作用,讓 if err != nil 的處理絲滑起來。

如下代碼:

try err, handler

編譯器翻譯后生成的代碼:

if err != nil {
return handler(err)
}

在函數(shù)中可以如下:

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

翻譯后生成的代碼:

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

也可以只針對 if err != nil 處理。如下代碼:

try err

翻譯后生成的代碼:

if err != nil {
return err
}

不會調(diào)用不存在的 handler 進(jìn)行處理,將會直接返回。三行(if err != nil 的邏輯)直接變 3 個單詞(try)。

不想寫函數(shù),也可以直接:

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

針對 defer+try 的場景可以如下:

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

入?yún)⑹潜容^靈活的,作者希望它是泛型,這樣能夠適配各種場景的要求。

示例和實(shí)踐

針對本提案,原作者給出了各類使用場景的示例。如下代碼:

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 }
}
}

另外在日常的 Go 工程中,提案作者認(rèn)為 CopyFile 函數(shù)是新提案語句的一種很好的實(shí)踐。為此基于 try-handler 進(jìn)行了一版改造和說明。

如下代碼:

// 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
}

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

  • 插入錯誤的返回語句,進(jìn)行機(jī)制預(yù)設(shè)。
  • 在返回錯誤之前將錯誤處理函數(shù)組合在一起,便于后續(xù)的處理。

總結(jié)

在這個新提案中,一旦實(shí)施,就可以減少如下代碼的編寫:

if err != nil {
return ...
}

在代碼編寫上會節(jié)省一些行數(shù),且可以為錯誤處理機(jī)制引入一些新的 ”操作“,這是該提案的優(yōu)勢。

但是從 Go 開發(fā)者的角度而言,會引入一些新的副作用,例如:初學(xué)者的學(xué)習(xí)成本、Go 工具鏈的改造、程序理解的復(fù)雜度增加。

另外新的語句,似乎比較難與 Go1.13 引入的 error.Is 和 As 有較好的相關(guān)聯(lián)性。如果是做一個第三方用戶庫引入倒可以,但若是作為標(biāo)準(zhǔn)進(jìn)入 Go 源代碼中,似乎又有些格格不入(提案作者希望進(jìn)入)。

看了那么多提案,Go 錯誤處理機(jī)制的 ”升級“,似乎陷入了手心手背都是肉的階段...

責(zé)任編輯:武曉燕 來源: 腦子進(jìn)煎魚了
相關(guān)推薦

2022-07-13 08:53:28

函數(shù)Go語言

2024-06-05 08:47:20

Go語言方式

2022-09-05 08:55:15

Go2提案語法

2024-11-19 09:10:19

迭代器Go語言

2025-02-08 09:57:20

2014-11-17 10:05:12

Go語言

2021-04-29 09:02:44

語言Go 處理

2023-07-11 08:46:38

閉包函數(shù)Rust

2025-04-29 08:05:00

JavaScript錯誤處理開發(fā)

2024-02-28 08:54:57

switchGo錯誤

2022-11-15 09:16:59

2025-03-31 00:29:44

2021-09-13 07:53:31

Go錯誤處理

2023-03-10 08:48:29

2024-03-27 08:18:02

Spring映射HTML

2023-10-26 15:49:53

Go日志

2021-09-27 15:33:48

Go 開發(fā)技術(shù)

2021-09-27 23:28:29

Go多協(xié)程并發(fā)

2020-12-17 06:25:05

Gopanic 模式

2021-09-27 10:04:03

Go程序處理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號