如何处理单例模式的错误只发生一次

huangapple go评论88阅读模式
英文:

How to handle error of singleton only once

问题

如何处理单例模式的错误只发生一次?

我有一个单例服务,只有在第一次调用时才会生成错误,然后它会返回已创建的实例。

服务的代码如下:

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()
   // 希望省略此错误处理
   if err != nil {
       return nil, err
   }
   return &serviceOne{database}, nil
}
func NewServiceTwo() (ServiceTwo, error) {
   database, err := NewDatabase()
   // 希望省略此错误处理
   if err != nil {
       return nil, err
   }
   return &serviceTwo{database}, nil
}
func NewServiceThree() (ServiceThree, error) {
   database, err := NewDatabase()
   // 希望省略此错误处理
   if err != nil {
       return nil, err
   }
   return &serviceThree{database}, nil
}

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

英文:

How to handle error of singleton only once?

I have a singleton service which could generate error only at first call and then it returns already created instance.

Service looks like below:

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
}

The problem is multiple services which uses databaseSingleton above handle error which can occurs only once.

Services which uses databaseSingleton looks like below:

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
}

If there any way to omit this error handling because err could be generated only once?

答案1

得分: 1

如果发生错误(仅发生一次),你的databaseSingleton将无法设置。你应该在所有情况下返回错误。

尽管这不是你可以做任何事情的问题(因为由于使用了sync.Once,初始化databaseSingleton的尝试不会重复),但你也可以停止应用程序。

实际上,延迟此初始化没有任何意义,你可以在包初始化期间进行初始化,并在失败时终止。如果成功,你可以在不检查初始化错误的情况下使用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}
}
英文:

If the error occurs (only once), your databaseSingleton will not be setup. You should return the error in all cases.

Although this isn't something you can do anything about (since the attempt to initialize databaseSingleton will not be repeated due to the use of sync.Once), you could as well halt the app.

In fact, there is no point deferring this initialization, you could just do it during package init, and terminate if it fails. And if it succeeds, you could use databaseSingleton without having to check error of the initialization.

So simply do it like this:

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() could look like this:

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

huangapple
  • 本文由 发表于 2022年3月2日 04:25:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/71314241.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定