编辑已 解决 :如何在GoLang中创建单例DBManager类。
我参考了一些有关如何创建单例的代码示例,但是我希望在其中包含方法,并在其单例引用中对其进行调用。我的代码如下
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并返回异常
一种方法是使用这些方法创建一个导出的接口,并使实现类型不导出。创建接口类型的全局变量,然后使用包init()函数对其进行初始化。您不需要任何同步,因为包init()功能只能安全地运行一次。
init()
init()在您可以从包中引用任何内容之前,包功能会在运行时自动执行一次。有关详细信息,请参见Spec:包初始化。
例如:
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(例如出于测试目的)。
newManager()
Mgr
Manager
注意: Mgr是一个导出的全局变量,可以通过其他包(例如dbprovider.Mgr = nil)为其分配新值。如果要避免这种情况,则必须使其不导出,并为其提供“获取”功能,例如:
dbprovider.Mgr = nil
var mgr = newManager() func Mgr() Manager { return mgr }
并使用它:
err := dbprovider.Mgr().AddArticle(someArticle)