如何创建单例数据库实例
How to create singleton DB instance
我提到了一些关于如何创建 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 和 return 异常
一种方法是使用方法创建导出接口,并使实现类型不导出。创建一个接口类型的全局变量,并用packageinit()
函数初始化。您不需要任何同步,因为包 init()
函数将 运行 安全地仅一次。
包 init()
函数在 运行 之前自动执行一次,然后您可以从包中引用任何内容。有关详细信息,请参阅 Spec: Package initialization。
例如:
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
是一个导出的全局变量,可以被其他包赋值给它(例如dbprovider.Mgr = nil
) .如果你想避免这种情况,你必须让它不被导出,并为它提供一个 "getter" 函数,例如:
var mgr = newManager()
func Mgr() Manager { return mgr }
并使用它:
err := dbprovider.Mgr().AddArticle(someArticle)
我提到了一些关于如何创建 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 和 return 异常一种方法是使用方法创建导出接口,并使实现类型不导出。创建一个接口类型的全局变量,并用packageinit()
函数初始化。您不需要任何同步,因为包 init()
函数将 运行 安全地仅一次。
包 init()
函数在 运行 之前自动执行一次,然后您可以从包中引用任何内容。有关详细信息,请参阅 Spec: Package initialization。
例如:
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
是一个导出的全局变量,可以被其他包赋值给它(例如dbprovider.Mgr = nil
) .如果你想避免这种情况,你必须让它不被导出,并为它提供一个 "getter" 函数,例如:
var mgr = newManager()
func Mgr() Manager { return mgr }
并使用它:
err := dbprovider.Mgr().AddArticle(someArticle)