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 在你的业务逻辑进行操作了。

注意这里需要先创建相关的数据库。

posted on 2024-08-03 15:01  进击的davis  阅读(261)  评论(0编辑  收藏  举报

导航