如何只处理一次单例错误

How to handle error of singleton only once

如何只处理一次单例错误?

我有一个单例服务,它只能在第一次调用时产生错误,然后它 returns 已经创建了实例。

服务如下所示:

package data

import (
    "sync"

    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

var (
    databaseSingleton *gorm.DB
    once              sync.Once
)

func NewDatabase() (*gorm.DB, error) {
    once.Do(func() {
        // ...
        databaseSingleton, err = gorm.Open(postgres.Open(connectionString), config)
        if err != nil {
            return nil, err
        }
    })
    return databaseSingleton, nil
}

问题是多个服务使用 databaseSingleton 以上句柄错误,只能发生一次。

使用 databaseSingleton 的服务如下所示:

func NewServiceOne() (ServiceOne, error) {
   database, err := NewDatabase()
   // want omit this error handling
   if err != nil {
       return nil, err
   }
   return &serviceOne{database}, nil
}
func NewServiceTwo() (ServiceTwo, error) {
   database, err := NewDatabase()
   // want omit this error handling
   if err != nil {
       return nil, err
   }
   return &serviceTwo{database}, nil
}
func NewServiceThree() (ServiceThree, error) {
   database, err := NewDatabase()
   // want omit this error handling
   if err != nil {
       return nil, err
   }
   return &serviceThree{database}, nil
}

如果因为 err 只能生成一次,是否有任何方法可以省略此错误处理?

如果错误发生(仅一次),您的 databaseSingleton 将不会被设置。在所有情况下,您都应该 return 错误。

虽然这不是您可以做的任何事情(因为初始化 databaseSingleton 的尝试由于使用 sync.Once 而不会重复),您也可以停止该应用程序.

事实上,推迟这个初始化是没有意义的,你可以在 package init 期间进行,如果失败则终止。如果成功,您可以使用 databaseSingleton 而无需检查初始化错误。

所以简单地这样做:

var databaseSingleton *gorm.DB

func init() {
    var err error
    databaseSingleton, err = gorm.Open(postgres.Open(connectionString), config)
    if err != nil {
        log.Fatalf("Failed to connect to DB: %v", err)
    }
}

NewServiceOne() 可能看起来像这样:

func NewServiceOne() ServiceOne {
   return &serviceOne{databaseSingleton}
}