单例模式-数据库单例

最后更新于:2022-04-02 02:35:36

[TOC] > [参考](https://tonybai.com/2021/02/09/create-and-get-db-access-instance-through-singleton/) ## db 案例
main.go ``` package main import ( "log" "os" "os/signal" "sync" "syscall" "github.com/bigwhite/testdboper/pkg/config" "github.com/bigwhite/testdboper/pkg/db" "github.com/bigwhite/testdboper/pkg/reader" "github.com/bigwhite/testdboper/pkg/updater" ) func init() { err := config.Init() // 初始化配置 if err != nil { panic(err) } } func main() { var wg sync.WaitGroup wg.Add(2) var quit = make(chan struct{}) // do some init from db _ = db.DB() go func() { updater.Run(quit) wg.Done() }() go func() { reader.Run(quit) wg.Done() }() c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) _ = <-c close(quit) log.Printf("recv exit signal...") wg.Wait() log.Printf("program exit ok") } ```

db.go ``` package db import ( "fmt" "sync" "time" "github.com/bigwhite/testdboper/pkg/config" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) var once sync.Once type database struct { instance *gorm.DB maxIdle int maxOpen int maxLifetime time.Duration } type Option func(db *database) var db *database func WithMaxIdle(maxIdle int) Option { return func(d *database) { d.maxIdle = maxIdle } } func WithMaxOpen(maxOpen int) Option { return func(d *database) { d.maxOpen = maxOpen } } func DB(opts ...Option) *gorm.DB { once.Do(func() { db = new(database) for _, f := range opts { f(db) } dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", config.Config.Database.User, config.Config.Database.Password, config.Config.Database.IP, config.Config.Database.Port, config.Config.Database.DB) var err error db.instance, err = gorm.Open("mysql", dsn) // database: *gorm.DB if err != nil { panic(err) } sqlDB := db.instance.DB() if err != nil { panic(err) } if db.maxIdle != 0 { sqlDB.SetMaxIdleConns(db.maxIdle) } if db.maxLifetime != 0 { sqlDB.SetConnMaxLifetime(db.maxLifetime) } if db.maxOpen != 0 { sqlDB.SetMaxOpenConns(db.maxOpen) } }) // 核心代码,初始化后,在返回实例 return db.instance } ```

reader.go ``` package reader import ( "log" "time" "github.com/bigwhite/testdboper/pkg/db" "github.com/bigwhite/testdboper/pkg/model" ) func dumpEmployee() { var rs []model.Employee // rs: record slice d := db.DB() d.Find(&rs) log.Println(rs) } func Run(quit <-chan struct{}) { tk := time.NewTicker(5 * time.Second) for { select { case <-tk.C: dumpEmployee() case <-quit: return } } } ```

';