web-dev-qa-db-ja.com

GoLangでシングルトンDBクラスを作成する方法

[〜#〜] editd [〜#〜]Solved: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(..)から例外をキャッチして返す方法

10
silentsudo

1つの方法は、メソッドを使用してエクスポートされたインターフェイスを作成し、実装タイプをエクスポートしないようにすることです。インターフェイスタイプのグローバル変数を作成し、パッケージinit()関数で初期化します。パッケージinit()関数は1回だけ安全に実行されるため、同期は必要ありません。

パッケージinit()関数は、パッケージから何かを参照する前に、ランタイムによって1回自動的に実行されます。詳細については、 仕様:パッケージの初期化 を参照してください。

例えば:

_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_)。これを回避したい場合は、エクスポートしないようにし、「ゲッター」関数を提供する必要があります。例:

_var mgr = newManager()

func Mgr() Manager { return mgr }
_

そしてそれを使用する:

_err := dbprovider.Mgr().AddArticle(someArticle)
_
17
icza