Baru-baru ini, cadangan percubaan baharu "cadangan: Pergi 2: pengendalian ralat: kenyataan cuba dengan pengendali[1]" telah mencetuskan perbincangan hangat dalam komuniti, mari kita lawan masyarakat semula! ! !
Hari ini Jianyu akan membukanya dengan semua orang dan melihat sama ada ini boleh membuka dan menyusun semula mekanisme pengendalian ralat Go. .
Faktor lain ialah diketahui umum bahawa kod pengendalian ralat Go agak menyusahkan Jurutera sering bergurau bahawa 30% daripada projek Go mempunyai jika err = nil. Kod berikut:
_, err := f() if err != nil { ... } _, err = r() if err != nil { ... } _, err = w() if err != nil { ... }
try err, handler
Kod yang dijana oleh pengkompil:
if err != nil { return handler(err) }
Dalam fungsi, ia boleh menjadi seperti berikut:
func(args...) (rtype1, rtypes..., rtypeN, error) { try err, handler ... }
Kod yang dihasilkan selepas terjemahan:
func(args...) (rtype1, rtypes..., rtypeN, error) { if err != nil { return Zero(rtype1), Zeros(rtypes...)..., Zero(rtypeN), handler(err) } ... }
Ia juga boleh diproses jika != tiada. Kod berikut:
try err
Jika anda tidak mahu menulis fungsi, anda juga boleh terus:
x, err := f() try err, fmt.Errorf("f fail: %w", err)
Senario penangguhan+cuba boleh seperti berikut:
func CopyFile(src, dst string) error { defer try func(err error) error { return fmt.Errorf("copy %s %s: %w", src, dst, err) } ... }
Parameter input lebih fleksibel, penulis berharap ia adalah generik bahawa ia boleh menyesuaikan diri dengan keperluan pelbagai senario.
针对本提案,原作者给出了各类使用场景的示例。如下代码:
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 工程中,提案作者认为 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 }
引入 try-hanlder 后,能够做到:
在这个新提案中,一旦实施,就可以减少如下代码的编写:
if err != nil { return ... }
在代码编写上会节省一些行数,且可以为错误处理机制引入一些新的 ”操作“,这是该提案的优势。
但是从 Go 开发者的角度而言,会引入一些新的副作用,例如:初学者的学习成本、Go 工具链的改造、程序理解的复杂度增加。
另外新的语句,似乎比较难与 Go1.13 引入的 error.Is 和 As 有较好的相关联性。如果是做一个第三方用户库引入倒可以,但若是作为标准进入 Go 源代码中,似乎又有些格格不入(提案作者希望进入)。
看了那么多提案,Go 错误处理机制的 ”升级“,似乎陷入了手心手背都是肉的阶段...
Atas ialah kandungan terperinci Cubalah Adakah cadangan baharu itu boleh dipercayai? Ingin memudahkan pengendalian ralat. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!