Golang Gorm框架初始化有哪些优雅的解决方案?

2026-05-22 06:061阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计971个文字,预计阅读时间需要4分钟。

Golang Gorm框架初始化有哪些优雅的解决方案?

Gorm解析,ORM框架,通过Config.yaml配置连接到本地MySQL数据库:host: 127.0.0.1

Gorm解析

gorm,orm框架

Config.yaml

mysql: host: 127.0.0.1 #地址 port: "3306" #端口 config: charset=utf8mb4&parseTime=True&loc=Local #配置 db-name: gva #数据库名称 username: root #账号 password: root #密码 max-idle-conns: 0 #最大空闲连接数 max-open-conns: 0 #最大连接数 log-mode: "" #是否开启Gorm全局日志 log-zap: false #是否打印日志到zap 配置文件

package config import ( "catering/pkg/e" ) type Mysql struct { Host string `json:"host" yaml:"host"` // 服务器地址 Port string `json:"port" yaml:"port"` // 端口 Config string `json:"config" yaml:"config"` // 高级配置 Dbname string `json:"dbname" yaml:"db-name"` // 数据库名 Username string `json:"username" yaml:"username"` // 数据库用户名 Password string `json:"password" yaml:"password"` // 数据库密码 MaxIdleConns int `json:"maxIdleConns" yaml:"max-idle-conns"` // 空闲中的最大连接数 MaxOpenConns int `json:"maxOpenConns" yaml:"max-open-conns"` // 打开到数据库的最大连接数 MaxLifeTime int `json:"maxLifeTime" yaml:"max-life-time"` LogMode string `json:"logMode" yaml:"log-mode"` // 是否开启Gorm全局日志 LogZap bool `json:"logZap" yaml:"log-zap"` // 是否通过zap写入日志文件 } func (m *Mysql) Check() error { if m.Username == "" || m.Dbname == "" { return e.ErrMysqlConfigCheckFail } return nil } func (m *Mysql) Dsn() string { return m.Username + ":" + m.Password + "@tcp(" + m.Host + ":" + m.Port + ")/" + m.Dbname + "?" + m.Config } 初始化

package initialize import ( "catering/global" "database/sql" "fmt" "log" "os" "time" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" ) func GormMysql() *gorm.DB { //获取配置文件的配置 cfg := global.Config.Mysql //检查配置 if err := cfg.Check(); err != nil { global.Log.Error(err.Error()) return nil } mysqlConfig := mysql.Config{ DSN: cfg.Dsn(), // DSN data source name DefaultStringSize: 255, // string 类型字段的默认长度 DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持 DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引 DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列 SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置 } //连接数据库 db, err := gorm.Open(mysql.New(mysqlConfig), getGormConfig()) if err != nil { return nil } sqlDB, _ := db.DB() if err := sqlDB.Ping(); err != nil { global.Log.Error(err.Error()) return nil } // 设置默认值 // SetMaxIdleConns 设置空闲连接池中连接的最大数量 sqlDB.SetMaxIdleConns(10) // SetMaxOpenConns 设置打开数据库连接的最大数量。 sqlDB.SetMaxOpenConns(100) // SetConnMaxLifetime 设置了连接可复用的最大时间。 sqlDB.SetConnMaxLifetime(time.Hour) Options(sqlDB, WithMaxIdelConns(cfg.MaxIdleConns), WithMaxOpenConns(cfg.MaxOpenConns), WithMaxLifeTime(cfg.MaxLifeTime)) return db } func getGormConfig() *gorm.Config { //禁用外键约束 config := &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true} //NewWriter 对log.New函数的再次封装,从而实现是否通过zap打印日志 _default := logger.New(NewWriter(log.New(os.Stdout, "\r\n", log.LstdFlags)), logger.Config{ SlowThreshold: 200 * time.Millisecond, LogLevel: logger.Warn, Colorful: true, }) //设置logger的日志输出等级 switch global.Config.Mysql.LogMode { case "silent", "Silent": config.Logger = _default.LogMode(logger.Silent) case "error", "Error": config.Logger = _default.LogMode(logger.Error) case "warn", "Warn": config.Logger = _default.LogMode(logger.Warn) case "info", "Info": config.Logger = _default.LogMode(logger.Info) default: config.Logger = _default.LogMode(logger.Info) } return config } type writer struct { logger.Writer } // NewWriter writer 构造函数 func NewWriter(w logger.Writer) *writer { return &writer{Writer: w} } // Printf 格式化打印日志 func (w *writer) Printf(message string, data ...interface{}) { var logZap bool switch global.Config.System.DbType { case "mysql": logZap = global.Config.Mysql.LogZap } //通过zap打印日志,或者其他 if logZap { global.Log.Info(fmt.Sprintf(message+"\n", data...)) } else { w.Writer.Printf(message, data...) } } //Option设计模式封装mysql的额外配置 type Option func(m *sql.DB) func WithMaxIdelConns(idle int) Option { return func(m *sql.DB) { if idle == 0 { return } m.SetMaxIdleConns(idle) } } func WithMaxOpenConns(open int) Option { return func(m *sql.DB) { if open == 0 { return } m.SetMaxOpenConns(open) } } func WithMaxLifeTime(t int) Option { return func(m *sql.DB) { if t == 0 { return } m.SetConnMaxLifetime(time.Duration(t) * time.Second) } } func Options(m *sql.DB, opts ...Option) { for _, opt := range opts { opt(m) } } 用法

package global import ( "github.com/go-redis/redis/v8" "go.uber.org/zap" "golang.org/x/sync/singleflight" "catering/config" "gorm.io/gorm" ) var ( DB *gorm.DB )

package initialize import ( "catering/global" "gorm.io/gorm" ) // Gorm 初始化数据库并产生数据库全局变量 // Author SliverHorn func InitGorm() { var db *gorm.DB switch global.Config.System.DbType { case "mysql": db = GormMysql() default: db = GormMysql() } global.DB = db }

package main import ( "catering/initialize" "catering/global" ) func main() { initialize.InitGorm() if global.DB != nil { db, _ := global.DB.DB() defer db.Close() } }

Golang Gorm框架初始化有哪些优雅的解决方案?

本文共计971个文字,预计阅读时间需要4分钟。

Golang Gorm框架初始化有哪些优雅的解决方案?

Gorm解析,ORM框架,通过Config.yaml配置连接到本地MySQL数据库:host: 127.0.0.1

Gorm解析

gorm,orm框架

Config.yaml

mysql: host: 127.0.0.1 #地址 port: "3306" #端口 config: charset=utf8mb4&parseTime=True&loc=Local #配置 db-name: gva #数据库名称 username: root #账号 password: root #密码 max-idle-conns: 0 #最大空闲连接数 max-open-conns: 0 #最大连接数 log-mode: "" #是否开启Gorm全局日志 log-zap: false #是否打印日志到zap 配置文件

package config import ( "catering/pkg/e" ) type Mysql struct { Host string `json:"host" yaml:"host"` // 服务器地址 Port string `json:"port" yaml:"port"` // 端口 Config string `json:"config" yaml:"config"` // 高级配置 Dbname string `json:"dbname" yaml:"db-name"` // 数据库名 Username string `json:"username" yaml:"username"` // 数据库用户名 Password string `json:"password" yaml:"password"` // 数据库密码 MaxIdleConns int `json:"maxIdleConns" yaml:"max-idle-conns"` // 空闲中的最大连接数 MaxOpenConns int `json:"maxOpenConns" yaml:"max-open-conns"` // 打开到数据库的最大连接数 MaxLifeTime int `json:"maxLifeTime" yaml:"max-life-time"` LogMode string `json:"logMode" yaml:"log-mode"` // 是否开启Gorm全局日志 LogZap bool `json:"logZap" yaml:"log-zap"` // 是否通过zap写入日志文件 } func (m *Mysql) Check() error { if m.Username == "" || m.Dbname == "" { return e.ErrMysqlConfigCheckFail } return nil } func (m *Mysql) Dsn() string { return m.Username + ":" + m.Password + "@tcp(" + m.Host + ":" + m.Port + ")/" + m.Dbname + "?" + m.Config } 初始化

package initialize import ( "catering/global" "database/sql" "fmt" "log" "os" "time" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" ) func GormMysql() *gorm.DB { //获取配置文件的配置 cfg := global.Config.Mysql //检查配置 if err := cfg.Check(); err != nil { global.Log.Error(err.Error()) return nil } mysqlConfig := mysql.Config{ DSN: cfg.Dsn(), // DSN data source name DefaultStringSize: 255, // string 类型字段的默认长度 DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持 DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引 DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列 SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置 } //连接数据库 db, err := gorm.Open(mysql.New(mysqlConfig), getGormConfig()) if err != nil { return nil } sqlDB, _ := db.DB() if err := sqlDB.Ping(); err != nil { global.Log.Error(err.Error()) return nil } // 设置默认值 // SetMaxIdleConns 设置空闲连接池中连接的最大数量 sqlDB.SetMaxIdleConns(10) // SetMaxOpenConns 设置打开数据库连接的最大数量。 sqlDB.SetMaxOpenConns(100) // SetConnMaxLifetime 设置了连接可复用的最大时间。 sqlDB.SetConnMaxLifetime(time.Hour) Options(sqlDB, WithMaxIdelConns(cfg.MaxIdleConns), WithMaxOpenConns(cfg.MaxOpenConns), WithMaxLifeTime(cfg.MaxLifeTime)) return db } func getGormConfig() *gorm.Config { //禁用外键约束 config := &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true} //NewWriter 对log.New函数的再次封装,从而实现是否通过zap打印日志 _default := logger.New(NewWriter(log.New(os.Stdout, "\r\n", log.LstdFlags)), logger.Config{ SlowThreshold: 200 * time.Millisecond, LogLevel: logger.Warn, Colorful: true, }) //设置logger的日志输出等级 switch global.Config.Mysql.LogMode { case "silent", "Silent": config.Logger = _default.LogMode(logger.Silent) case "error", "Error": config.Logger = _default.LogMode(logger.Error) case "warn", "Warn": config.Logger = _default.LogMode(logger.Warn) case "info", "Info": config.Logger = _default.LogMode(logger.Info) default: config.Logger = _default.LogMode(logger.Info) } return config } type writer struct { logger.Writer } // NewWriter writer 构造函数 func NewWriter(w logger.Writer) *writer { return &writer{Writer: w} } // Printf 格式化打印日志 func (w *writer) Printf(message string, data ...interface{}) { var logZap bool switch global.Config.System.DbType { case "mysql": logZap = global.Config.Mysql.LogZap } //通过zap打印日志,或者其他 if logZap { global.Log.Info(fmt.Sprintf(message+"\n", data...)) } else { w.Writer.Printf(message, data...) } } //Option设计模式封装mysql的额外配置 type Option func(m *sql.DB) func WithMaxIdelConns(idle int) Option { return func(m *sql.DB) { if idle == 0 { return } m.SetMaxIdleConns(idle) } } func WithMaxOpenConns(open int) Option { return func(m *sql.DB) { if open == 0 { return } m.SetMaxOpenConns(open) } } func WithMaxLifeTime(t int) Option { return func(m *sql.DB) { if t == 0 { return } m.SetConnMaxLifetime(time.Duration(t) * time.Second) } } func Options(m *sql.DB, opts ...Option) { for _, opt := range opts { opt(m) } } 用法

package global import ( "github.com/go-redis/redis/v8" "go.uber.org/zap" "golang.org/x/sync/singleflight" "catering/config" "gorm.io/gorm" ) var ( DB *gorm.DB )

package initialize import ( "catering/global" "gorm.io/gorm" ) // Gorm 初始化数据库并产生数据库全局变量 // Author SliverHorn func InitGorm() { var db *gorm.DB switch global.Config.System.DbType { case "mysql": db = GormMysql() default: db = GormMysql() } global.DB = db }

package main import ( "catering/initialize" "catering/global" ) func main() { initialize.InitGorm() if global.DB != nil { db, _ := global.DB.DB() defer db.Close() } }

Golang Gorm框架初始化有哪些优雅的解决方案?