处理 defer 中的错误

dem*_*mas 13 go

我有一个打开数据库连接并返回它的函数。或错误,如果发生了什么:

OpenDbConnection(connectionString string, logSql bool) (*gorm.DB, error) 
Run Code Online (Sandbox Code Playgroud)

在这个函数中,我使用了记录器:

logger := zap.NewExample().Sugar()
defer logger.Sync()
Run Code Online (Sandbox Code Playgroud)

方法Sync()返回error,我忽略了这个错误。

在这种情况下最好的策略是什么?

我可以重写我的代码以避免 linter 错误,但我仍然忽略错误:

logger := zap.NewExample().Sugar()
defer func() {
    _ = logger.Sync()
}()
Run Code Online (Sandbox Code Playgroud)

我可以返回错误,但我有正确的数据库连接,我需要在调用函数中分析此错误以了解该怎么做。

Ahm*_*hem 8

您可以命名返回的错误变量并在函数内的任何位置进行初始化。

在此处检查此测试代码

OpenDbConnection(connectionString string, logSql bool) (db *gorm.DB, err error) {

    logger := zap.NewExample().Sugar()
    defer func() {
        err = logger.Sync()
    }()

    // some logic here

    return db, err

}
Run Code Online (Sandbox Code Playgroud)

  • 所写的缺陷是,如果在“// somelogic here”部分中设置了错误(例如,“if ... { err :=Errors.New("bad"); return nil, err; }`)您将用“logger.Sync”的结果“覆盖”它。如果“logger.Sync”成功,即使实际打开失败,也可能会导致返回*no*错误。 (11认同)
  • 你是对的。为了绕过这种情况,我们可以返回一个错误数组“errs []error”,其中包含延迟错误和逻辑错误。 (2认同)
  • 或者你可以在 defer 中检查 `logger.Sync()` 返回的错误,并且仅在它不为 nil 时覆盖 `err` 变量。 (2认同)

zan*_*ngw 5

接受的答案的另一个陷阱是错误检查,例如

OpenDbConnection(connectionString string, logSql bool) (db *gorm.DB, err error) {
    logger := zap.NewExample().Sugar()
    defer func() {
        errS := logger.Sync()
        if errS != nil {
           err = errS
        }
    }()

   // some logic here
Run Code Online (Sandbox Code Playgroud)

如果变量是在调用函数之前的部分err设置的。原始错误可以被该错误覆盖。some logicdeferlogger.Sync()


Go 1.20中,errors.Join添加了 来处理多个错误

新函数errors.Join返回一个包含错误列表的错误。

OpenDbConnection(connectionString string, logSql bool) (db *gorm.DB, err error) {
    logger := zap.NewExample().Sugar()
    defer func() {
        err = errors.Join(err, logger.Sync())
    }()

   // some logic here
Run Code Online (Sandbox Code Playgroud)

现在,如果发生任何错误,err将会被设置。如果两个错误都存在,我们会收到一个新错误,其中它们与\n分隔符连接在一起。