编写通用错误处理函数(必须函数)

问题描述 投票:0回答:4

我知道 Go 将来不会有泛型,并且有一些建议可以用其他结构来替换它们。但通过我下面的例子,我陷入了困境。

func P(any interface{}, err error) (interface{}) {
    if err != nil {
        panic("error: "+ err.Error())
    }
    return any
}

正如您可能猜到的那样,我试图在任何错误上失败,并希望将

P()
放在任何返回两个结果的函数周围,第二个是错误。这工作正常,但是
any
正在丢失它的类型信息,并且结果中只是一个空接口。

由于我也在调用 lib 函数,所以我没有找到使用接口或反射来解决此问题的方法。

有什么想法吗?我是否完全走错了路或者已经接近目标了?

go generics error-handling
4个回答
12
投票

一种解决方案是

go generate
您的
P()
函数,针对您需要使用的每种具体类型。
请参阅以下示例:

这将使调用这些 lib 函数变得更容易,因为生成的具体 P () 实现将使用正确的类型而不是 interface{}。


8
投票

Go 1.18 泛型更新: Go 1.18 添加了泛型支持,现在可以编写泛型

Must()
函数:

func Must[T any](v T, err error) T {
    if err != nil {
        panic(err)
    }
    return v
}

这可以在

github.com/icza/gog
中获得,如
gog.Must()
(披露:我是作者)。

1.18 之前的原始答案如下。


你想要做的需要泛型,但正如你已经提到的,Go 不支持泛型类型。因此,您无法创建一个不会丢失类型的通用函数。

您必须为您想要支持的每种类型创建这样的函数。请注意,标准库已包含其中一些名称为

MustXXX()

 的内容,您可以开箱即用,例如:

template.Must(t *Template, err error) *Template


或抑制

error

 的“类似”功能,但如果仍然发生,则会出现恐慌,例如:

regexp.MustCompile(str string) *Regexp

(抑制 error
,但如果 
str
 不是有效的正则表达式,则会出现恐慌)


4
投票
如果您打算只是对错误感到恐慌

(坏主意)或记录它们,那么只需定义一个函数来执行此操作并使用它即可。例如

func checkErr(err error) { if err != nil { log.Println(err) } } // ... func foo() { a, err := doA() checkErr(err) b, err := doB() checkErr(err) // etc. }

用户twotwotwo已经链接到

错误是值文章,其中展示了有关如何减少错误处理重复性的更多示例。但我建议只写整个 if err != nil

 的事情,因为根据我的经验,每第三个错误(如果不是第二个)都需要一些额外的处理。


1
投票
Go 1.18(2022 年初)将在该语言中引入类型参数。

根据当前的

accepted proposal 规范,您将能够编写通用的 Must

 函数,而无需牺牲类型安全性。

它将如下所示:

package main import ( "fmt" "errors" ) func Must[T any](v T, err error) T { if err != nil { panic("error: " + err.Error()) } return v } func main() { fmt.Println(Must(test1())) // 450 fmt.Println(Must(test2())) // panics... } func test1() (int, error) { return 450, nil } func test2() (string, error) { return "", errors.New("problem") }
Go2 游乐场:

https://go2goplay.golang.org/p/SHqZc5LYeAB

© www.soinside.com 2019 - 2024. All rights reserved.