go-zero 微服务框架集成 gorm 实操
作为服务,肯定要和数据库交互的,所以在 go-zero 框架里集成 数据库 的操作是必不可少的,今天看看 go-zero 的 rpc 应用如何集成 gorm 框架。
总体的思路分这几步:
- 定义你的配置项结构体
- 定义你的配置
- 添加到 svcContext
- 实现你的模型
- 具体业务逻辑的应用
1.config 的结构体
package config
import (
"github.com/zeromicro/go-zero/zrpc"
)
type Config struct {
zrpc.RpcServerConf
MySQLConf MySQLConf
}
// Mysql config
type MySQLConf struct {
Host string `json:"" yaml:"Host"`
Port int64 `json:"" yaml:"Port"`
User string `json:"" yaml:"User"`
Password string `json:"" yaml:"Password"`
Database string `json:"" yaml:"Database"`
CharSet string `json:"" yaml:"CharSet"`
TimeZone string `json:"" yaml:"TimeZone"`
ParseTime bool `json:"" yaml:"ParseTime"`
Enable bool `json:"" yaml:"Enable"` // use mysql or not
//DefaultStringSize uint `json:"" yaml:"DefaultStringSize"` // string 类型字段的默认长度
AutoMigrate bool `json:"" yaml:"AutoMigrate"`
//DisableDatetimePrecision bool `json:"" yaml:"DisableDatetimePrecision"` // 禁用 datetime 精度
//SkipInitializeWithVersion bool `json:"" yaml:"SkipInitializeWithVersion"` // 根据当前 MySQL 版本自动配置
//
//SlowSql time.Duration `json:"" yaml:"SlowSql"` //慢SQL
//LogLevel string `json:"" yaml:"LogLevel"` // 日志记录级别
//IgnoreRecordNotFoundError bool `json:"" yaml:"IgnoreRecordNotFoundError"` // 是否忽略ErrRecordNotFound(未查到记录错误)
Gorm GormConf `json:"" yaml:"Gorm"`
}
// gorm config
type GormConf struct {
//SkipDefaultTx bool `json:"" yaml:"SkipDefaultTx"` //是否跳过默认事务
//CoverLogger bool `json:"" yaml:"CoverLogger"` //是否覆盖默认logger
//PreparedStmt bool `json:"" yaml:"PreparedStmt"` // 设置SQL缓存
//CloseForeignKey bool `json:"" yaml:"CloseForeignKey"` // 禁用外键约束
SingularTable bool `json:"" yaml:"SingularTable"` //是否使用单数表名(默认复数),启用后,User结构体表将是user
TablePrefix string `json:"" yaml:"TablePrefix"` // 表前缀
MaxOpenConns int `json:"" yaml:"MaxOpenConns"`
MaxIdleConns int `json:"" yaml:"MaxIdleConns"`
ConnMaxLifetime int `json:"" yaml:"ConnMaxLifetime"`
}
2.配置文件声明
MySQLConf:
Enable: true
User: user1
Password: user1
Host: x.x.x.x
Port: 3306
Database: zero
CharSet: utf8
ParseTime: true
TimeZOne: Local
AutoMigrate: true
Gorm:
TablePrefix: zero_
SingularTable: true
MaxOpenConns: 100
MaxIdleConns: 5
ConnMaxLifetime: 600
3.添加 svcContext
package svc
import (
"fmt"
"time"
"userrpcv1/internal/config"
"userrpcv1/internal/models"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/schema"
)
type ServiceContext struct {
Config config.Config
// claim ur redis client in here
//RedisClient *zeroRds.Redis
// claim ur mysql here
DBEngine *gorm.DB
}
func NewServiceContext(c config.Config) *ServiceContext {
// redis
//conf := c.Redis
//redisClient := zeroRds.MustNewRedis(conf.RedisConf)
// mysql
mysqlConf := c.MySQLConf
var db *gorm.DB
var err error
if mysqlConf.Enable {
db, err = creteDbClient(mysqlConf)
if err != nil {
db = nil
}
}
return &ServiceContext{
Config: c,
//RedisClient: redisClient,
DBEngine: db,
}
}
func creteDbClient(mysqlConf config.MySQLConf) (*gorm.DB, error) {
datasource := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=%t&loc=%s",
mysqlConf.User,
mysqlConf.Password,
mysqlConf.Host,
mysqlConf.Port,
mysqlConf.Database,
mysqlConf.CharSet,
mysqlConf.ParseTime,
mysqlConf.TimeZone)
db, err := gorm.Open(mysql.Open(datasource), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
TablePrefix: mysqlConf.Gorm.TablePrefix, // such as: prefix_tableName
SingularTable: mysqlConf.Gorm.SingularTable, // such as zero_user, not zero_users
},
})
if err != nil {
logx.Errorf("create mysql db failed, err: %v", err)
return nil, err
}
// auto sync table structure, no need to create table
err = db.AutoMigrate(&models.User{})
if err != nil {
logx.Errorf("automigrate table failed, err: %v", err)
}
logx.Info("init mysql client instance success.")
sqlDB, err := db.DB()
if err != nil {
logx.Errorf("mysql set connection pool failed, err: %v.", err)
return nil, err
}
sqlDB.SetMaxOpenConns(mysqlConf.Gorm.MaxOpenConns)
sqlDB.SetMaxIdleConns(mysqlConf.Gorm.MaxIdleConns)
sqlDB.SetConnMaxLifetime(time.Duration(mysqlConf.Gorm.ConnMaxLifetime) * time.Second)
return db, nil
}
4.定义你的相关表或者模型
models/user.go
package models
import "time"
// base model
type BaseModel struct {
ID int64 `json:"id" gorm:"column:id;autoIncrement;primaryKey"`
CreatedAt time.Time `json:"createdAt" gorm:"column:createdAt"`
UpdatedAt time.Time `json:"updatedAt" gorm:"column:updatedAt"`
DeletedAt time.Time `json:"-" gorm:"column:deletedAt"`
}
// user table
type User struct {
BaseModel
Username string `json:"username" gorm:"column:username;type:varchar(20);unique:un_username;not null;comment:用户名"`
NickName string `json:"nickName" gorm:"column:nickname;type:varchar(20);not null;default:'-';comment:昵称"`
Phone int `json:"phone" gorm:"column:phone;type:int;unique:un_phone;comment:手机号"`
Password string `json:"-" gorm:"column:password;type:varchar(40);comment:密码"`
Status int8 `json:"status" gorm:"column:status;size:4;default:1;comment:状态 1:正常 2:白名单 3:黑名单"`
IsAdmin bool `json:"is_admin" gorm:"column:is_admin;default:false"`
}
// userProfile table
type UserInfo struct {
BaseModel
Address string `json:"address" gorm:"column:address;type:varchar(100)"`
Uid uint `json:"uid" gorm:"column:uid;comment:用户id"`
}
接着你就可以拿到 db 在你的业务逻辑进行操作了。
注意这里需要先创建相关的数据库。