6

是否有更内置的包装器来使返回(X, error)成功的函数执行或中止,例如regexp.MustCompile

我说的是这样的东西,但更多的是“内置”。

4

4 回答 4

3

那没有。你会得到最好的东西是这样的:

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
}

冗长而乏味,但至少它是明确且易于理解的。以下是我编写的两个模块,它们迫切需要参数多态性,它们可能会给你一些在没有它的情况下处理的想法:

于 2012-09-16T23:36:10.810 回答
2

我认为内置机制没有意义,因为您可以很好地以各种方式处理非零错误,模板包本身的示例也是如此:参见“ 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 程序(如本线程中所讨论的那样),并且涵盖处理错误的所有可能方式将意味着创建很多“内置”机制。

于 2012-09-15T12:16:48.670 回答
0

我自己也遇到过同样的问题,决定开发以下解决方案: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;
    ...
`))
于 2019-05-30T12:28:31.110 回答
0

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根据代码中的需要实现变体。

  1. https://github.com/golang/go/blob/go1.16.5/src/regexp/regexp.go#L305-L314
于 2021-07-06T20:18:17.283 回答