已编辑 已解决:如何在GoLang中创建单例DBManager类。
我提到了如何创建go单例的几个代码示例,但我希望在这些中有方法并在他们的单例引用上调用它们。我的代码如下
package dbprovider
import (
"github.com/jinzhu/gorm"
_"github.com/jinzhu/gorm/dialects/sqlite"
"rest/article"
"log"
)
type DBOperations interface {
AddArticle(article *article.Article)
}
type DBManager struct {
db *gorm.DB
isInitialized bool
}
var dbManagerInstance = new()
func GetDBManager() DBManager {
return dbManagerInstance
}
func new() DBManager {
localDbRef, err := gorm.Open("sqlite3", "../articles.db")
if (err != nil) {
panic("Error initializing db")
} else {
log.Print("DB Initialized successfully")
}
return DBManager{db:localDbRef, isInitialized:true}
}
func (dbManager DBManager) AddArticle(article article.Article) (err error) {
if (dbManager.isInitialized) {
tx := dbManager.db.Begin()
//dbManager.db.NewRecord(article)
//dbManager.db.Commit()
tx.NewRecord(article)
tx.Commit()
errs := dbManager.db.GetErrors()
if (len(errs) > 0) {
err = errs[0]
} else {
log.Print("No error in this transactions")
}
}
return
}
我已经更新了这个问题,包括答案。但我几乎没有疑问。如何从gorm.Create(..)
中进行cathc并返回异常答案 0 :(得分:13)
一种方法是使用方法创建导出的接口,并使实现类型不导出。创建接口类型的全局变量,并使用包ImageProvider
函数对其进行初始化。您不需要任何同步,因为包init()
函数将只安全运行一次。
程序包init()
函数由运行时自动执行一次,然后才能从程序包中引用任何内容。有关详细信息,请参阅Spec: Package initialization。
例如:
init()
使用它:
package dbprovider
type Manager interface {
AddArticle(article *article.Article) error
// Add other methods
}
type manager struct {
db *gorm.DB
}
var Mgr Manager
func init() {
db, err := gorm.Open("sqlite3", "../articles.db")
if err != nil {
log.Fatal("Failed to init db:", err)
}
Mgr = &manager{db: db}
}
func (mgr *manager) AddArticle(article *article.Article) (err error) {
mgr.db.Create(article)
if errs := mgr.db.GetErrors(); len(errs) > 0 {
err = errs[0]
}
return
}
您也可以在没有import "dbprovider"
if err := dbprovider.Mgr.AddArticle(someArticle); err != nil {
// Handle error
}
功能的情况下执行此操作,例如:
init()
有了这个,您可以决定导出var Mgr = newManager()
func newManager() Manager {
db, err := gorm.Open("sqlite3", "../articles.db")
if err != nil {
log.Fatal("Failed to init db:", err)
}
return &manager{db: db}
}
,并且您的软件包的用户可以决定使用共享的newManager()
实例,或者他们可以创建另一个Mgr
,例如用于测试目的。
注意: Manager
是一个导出的全局变量,可以通过其他包为其分配新值(例如Mgr
)。如果你想避免这种情况,你必须使它成为未导出的,并提供一个" getter"它的功能,例如:
dbprovider.Mgr = nil
使用它:
var mgr = newManager()
func Mgr() Manager { return mgr }