写点什么

Go-Zero 数据库实战:配置、建模与业务逻辑一体化

作者:王中阳Go
  • 2024-07-26
    北京
  • 本文字数:4671 字

    阅读完需:约 15 分钟

Go-Zero 数据库实战:配置、建模与业务逻辑一体化

前言

在之前的几篇文章中,我们深入学习了 Go-Zero 框架的实战应用,包括模板定制化、API 定义、抽奖算法设计等内容。本文将继续探索 Go-Zero 框架的实践技巧,并介绍一些与数据库操作相关的主题。


在现代应用程序开发中,对数据库的操作是非常常见且重要的一部分。Go-Zero 框架提供了强大的数据库支持,使得我们可以轻松地进行数据库访问和操作。本文将重点介绍如何使用 Go-Zero 框架进行数据库的增删改查(CRUD)操作,并提供详细的示例代码和解释。


在本文中,我们将使用 MySQL 数据库作为示例,并结合 Go-Zero 框架的相关组件,如数据模型(Model)、事务处理、连接池等,来展示数据库操作的最佳实践。无论你是初学者还是有一定经验的开发者,本文都将为你提供有用的信息和技巧,帮助你更好地理解和应用 Go-Zero 框架中的数据库操作。


在阅读本文之前,请确保你已经按照前几篇文章中的说明进行了必要的准备工作,包括安装所需的工具和设置项目环境。同时,本文假设你已经具备一定的数据库基础知识,如表的创建、数据的插入和查询等。


通过学习本文,你将掌握以下内容:


  • 如何配置和初始化数据库连接;

  • 如何使用 Go-Zero 框架的 Model 组件进行数据表的创建和映射;

  • 如何进行常见的 CRUD 操作,包括数据的插入、查询、更新和删除;

  • 如何处理数据库事务;

  • 实现用户注册业务逻辑。


我们鼓励你跟随示例代码,动手实践,并根据自己的需求进行定制和扩展。无论是为了学习 Go-Zero 的数据库操作,还是为了解决具体的业务问题,本文都将为你提供实用的指导和技巧。


祝你阅读愉快,并从中获得所需的知识和灵感!

实战前准备

本次实战我们是建立在(六)Go-Zero实战之docker开发环境部署 基础之上,如果没有学习过,可以点击跳转学习,然后再看本文哦!


本次实战采用的是 docker 部署,请提前准备好相关环境,关于 docker 环境的搭建在(六)Go-Zero实战之docker开发环境部署 中也有讲解,不了解小伙伴建议先行实战 docker 环境搭建哦!

目录结构说明


  • 在 app 下面我们将会新建一个服务 comment,表示晒单评论服务,deploy/sql 存放的是我们的建表语句,相关语句将会在接下来的讲解中给大家。

实战

配置 docker 组件

  • 在 docker-commpose-env.yml 中添加如下配置 mysql



  mysql:    image: mysql/mysql-server:8.0.28    container_name: mysql    environment:      # 时区上海 - Time zone Shanghai (Change if needed)      TZ: Asia/Shanghai      # root 密码 - root password      MYSQL_ROOT_PASSWORD: xxxxxx #这里填上mysql的密码    ports:      - 33069:3306    volumes:      # 数据挂载 - Data mounting      - ./data/mysql/data:/var/lib/mysql      # 日志    command:      # 将mysql8.0默认密码策略 修改为 原先 策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配)       # Modify the Mysql 8.0 default password strategy to the original strategy (MySQL8.0 to change its default strategy will cause the password to be unable to match)      --default-authentication-plugin=mysql_native_password      --character-set-server=utf8mb4      --collation-server=utf8mb4_general_ci      --explicit_defaults_for_timestamp=true      --lower_case_table_names=1    privileged: true    restart: always    networks:      - testProject_net
复制代码


  • 在本次实战中我们会使用到缓存(使用 sqlc 库),因此也进行了 redis 的配置。如果不想走缓存,可以使用 sqlx 库,后续根据需求再添加缓存。

  • 在 docker-commpose-env.yml 中添加如下配置 redis



  #redis容器 - Redis container  redis:    image: redis:6.2.5    container_name: redis    ports:      - 36379:6379    environment:      # 时区上海 - Time zone Shanghai (Change if needed)      TZ: Asia/Shanghai    volumes:      # 数据文件 - data files      - ./data/redis/data:/data:rw    command: "redis-server --requirepass G62m50oigInC30sf  --appendonly yes"    privileged: true    restart: always    networks:      - testProject_net
复制代码


  • 在进行复制粘贴的时候需要注意缩进哦!

重新启动项目所依赖的环境

$ docker-compose -f docker-compose-env.yml up -d
复制代码


Navicate 连接数据库

Go-Zero 操作数据库

go-zero 提供了两个操作数据库的库,分别是 sqlc 和 sqlx。区别是前者带缓存,后者不带缓存。



我们先在(六)Go-Zero实战之docker开发环境部署 中创建的 usercent 服务进行 gozero 操作数据库相关内容的学习



使用脚本生成数据库对应的 model


#!/usr/bin/env bash
# 使用方法:# ./genModel.sh lottery lottery# ./genModel.sh lottery prize# ./genModel.sh looklook_usercenter user_contact# 再将./genModel下的文件剪切到对应服务的model目录里面,记得改package
#生成的表名tables=$2#表生成的genmodel目录modeldir=./genModel
# 数据库配置host=127.0.0.1port=33069dbname=$1username=rootpasswd=PXDN93VRKUm8TeE7template=../../goctl/1.6.1
echo "开始创建库:$dbname 的表:$2"goctl model mysql datasource -url="${username}:${passwd}@tcp(${host}:${port})/${dbname}" -table="${tables}" -dir="${modeldir}" -cache=true --home="${template}" --style=goZero
复制代码


  • 使用 GitBash 打开 deploy/script/mysql 目录,执行脚本



  • 将相关代码放到 model 下



  • 把包名改成 model



  • 配置文件中加入如下配置,用于 jwt 鉴权以及 mysql、redis 连接配置的获取



package config
import ( "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/zrpc")
type Config struct { zrpc.RpcServerConf CheckinRpcConf zrpc.RpcClientConf JwtAuth struct { AccessSecret string AccessExpire int64 } DB struct { DataSource string } Cache cache.CacheConf}
复制代码


  • svc 下的 serviceContext 加入如下配置,用于获取 mysql 连接



package svc
import ( "github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/sqlx" "testProject/app/usercenter/cmd/rpc/internal/config" "testProject/app/usercenter/model")
type ServiceContext struct { Config config.Config UserModel model.UserModel
RedisClient *redis.Redis}
func NewServiceContext(c config.Config) *ServiceContext { sqlConn := sqlx.NewMysql(c.DB.DataSource)
return &ServiceContext{ UserModel: model.NewUserModel(sqlConn, c.Cache), Config: c, }}
复制代码


  • rpc/etc/usercenter.yaml 加上 jwtAuth 配置


#jwtAuthJwtAuth:  AccessSecret: ae0536f9-6450-4606-8e13-5a19ed505da0  AccessExpire: 31536000
复制代码


  • 注册 model



UserModel:        model.NewUserModel(sqlConn, c.Cache),
复制代码


  • 这样我们就可以在 userModel 下写我们自己的 sql 操作了


事务操作

  • sqlc 为我们提供了事务操作,相关源码如下:



  • 我们可以基于官方提供的 TransactCtx 方法,封装自己的事务处理方法

  • 首先在 userModel 里面注册 Trans 方法,如下图所示



Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error
复制代码


  • 接着写这个方法的实现,其实就是对原本的函数进行了一个封装。



func (m *defaultUserModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error {    return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {       return fn(ctx, session)    })}
复制代码


  • 通过这个例子,我们可以知道 gozero 如何注册自己的数据库操作方法,以及了解到如何进行事务操作。

注册业务逻辑的实现

  • 首先我们先在 tool 下新增 encryption.go 文件,增加一个 md5 加密字符串的函数



func Md5ByString(str string) string {  m := md5.New()  _, err := io.WriteString(m, str)  if err != nil {    panic(err)  }  arr := m.Sum(nil)  return fmt.Sprintf("%x", arr)}
复制代码


  • 在 logic/registerLogic.go 里面编写我们的注册逻辑,注册业务代码如下


func (l *RegisterLogic) Register(in *pb.RegisterReq) (*pb.RegisterResp, error) {    if err := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {       user := new(model.User)       if len(in.Password) > 0 {          user.Password = tool.Md5ByString(in.Password)       }       insertResult, err := l.svcCtx.UserModel.Insert(ctx, user)       if err != nil {          return errors.Wrapf(err, "Register db user Insert err:%v,user:%+v", err, user)       }       lastId, err := insertResult.LastInsertId()       if err != nil {          return errors.Wrapf(err, "Register db user insertResult.LastInsertId err:%v,user:%+v", err, user)       }       fmt.Println("lastId:", lastId)
return nil }); err != nil { logx.Error("Register:", err) return nil, err }
return &usercenter.RegisterResp{}, nil
}
复制代码


  • tips:这个是最简单的插入一条数据的逻辑,实际生产中我们往往需要添加各种校验以及登录回调,jwt 返回等,根据实际需求进行修改。如果读者朋友有需求,后续文章我们也会完善这个注册逻辑。

  • 可以看见我们实际调用了 Insert 方法进行了插入操作。gozero 框架的默认模板帮我们封装好了常规的增删改查操作,我们可以直接调用即可,如果有额外需求我们可以在 userModel.go 定义自己的 sql 查询方法,或者自定义我们自己的 goctl,关于自定义模板可以看我前面的文章(四)Go-Zero自定义goctl实战:定制化模板,加速你的微服务开发效率哦!

  • 接下来我们简单看一下模板中对于增删查改方法的实现

  • 插入操作



  • 删除操作



  • 更新操作



  • 查询操作



测试与验证





  • 可以看见成功进行了用户注册,说明插入操作有效。

结语

至此,我们已经完成了数据库相关配置,以及通过用户服务和注册接口了解到了常规的增删改查操作。


关于更详细的实现,如果有小伙伴有需求,我们可以单独拿一节课来进行详细的拆分讲解。


本篇文章介绍了 Go-Zero 中的数据库操作,并提供了常用的命令示例。通过学习和实践,我们可以更加熟练地使用 Go-Zero 进行高效的数据库操作。在后续的文章中,我们将进一步探索数据库操作的高级用法和技巧,为小伙伴们提供更多的参考。

欢迎关注 ❤

我的文章都首发在同名公众号:王中阳


需要简历优化或者就业辅导,可以直接加我微信:wangzhongyang1993,备注:infoq

用户头像

王中阳Go

关注

靠敲代码在北京买房的程序员 2022-10-09 加入

【微信】wangzhongyang1993【公众号】程序员升职加薪之旅【成就】InfoQ专家博主👍掘金签约作者👍B站&掘金&CSDN&思否等全平台账号:王中阳Go

评论

发布
暂无评论
Go-Zero 数据库实战:配置、建模与业务逻辑一体化_数据库_王中阳Go_InfoQ写作社区