是否有更内置的包装器来使返回(X, error)
成功的函数执行或中止,例如regexp.MustCompile
?
我说的是这样的东西,但更多的是“内置”。
那没有。你会得到最好的东西是这样的:
func Must(fn func() (interface{}, error)) interface{} {
v, err := fn()
if err != nil {
log.Fatalln(err)
}
return v
}
然后使用它:
Must(func() (interface{}, error) {
return template.ParseGlob(pattern)
}).(*template.Template)
假设这template.ParseGlob(pattern)
是您想要包装的电话。
Go 没有参数多态性,因此这种代码最终将需要类型断言来恢复原始类型,因此(在我看来)付出的努力多于其价值。对于长链的潜在故障,您将获得的最简洁、惯用的错误处理就是检查错误并返回它。推迟清理处理程序:
func MyFunc() (err error) {
a, err := blah1()
if err != nil {
return
}
defer a.Close()
b, err := blah2(a)
if err != nil {
return
}
defer b.Close()
// ad nauseam
}
冗长而乏味,但至少它是明确且易于理解的。以下是我编写的两个模块,它们迫切需要参数多态性,它们可能会给你一些在没有它的情况下处理的想法:
我认为内置机制没有意义,因为您可以很好地以各种方式处理非零错误,模板包本身的示例也是如此:参见“ text/template/examplefiles_test.go
”,说明了 ' ' 的两种不同用法err
:
// Here starts the example proper.
// T0.tmpl is the first name matched, so it becomes the starting template,
// the value returned by ParseGlob.
tmpl := template.Must(template.ParseGlob(pattern))
err := tmpl.Execute(os.Stdout, nil)
if err != nil {
log.Fatalf("template execution: %s", err)
}
// Output:
// T0 invokes T1: (T1 invokes T2: (This is T2))
在辅助函数的特定情况下(*Template) Must()
,将错误转换为异常(恐慌)并不总是适用于所有go 程序(如本线程中所讨论的那样),并且涵盖处理错误的所有可能方式将意味着创建很多“内置”机制。
我自己也遇到过同样的问题,决定开发以下解决方案:https ://github.com/boramalper/must
例子:
database := must.MV(sql.Open("sqlite3", "...")).(*sql.DB)
defer must.M(database.Close())
must.M(database.Ping())
// Use MustValVoid (or MVV shortly) if you don't care about
// the return value.
must.MVV(database.Exec(`
PRAGMA foreign_key_check;
...
`))
log
当源本身使用时,我不确定为什么这里的所有答案都使用包panic
:
func MustCompile(str string) *Regexp {
regexp, err := Compile(str)
if err != nil {
panic(`regexp: Compile(` + quote(str) + `): ` + err.Error())
}
return regexp
}
我的建议不是通用Must
包装器,而是
Must
根据代码中的需要实现变体。