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.28container_name: mysqlenvironment:# 时区上海 - Time zone Shanghai (Change if needed)TZ: Asia/Shanghai# root 密码 - root passwordMYSQL_ROOT_PASSWORD: xxxxxx #这里填上mysql的密码ports:- 33069:3306volumes:# 数据挂载 - 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=1privileged: truerestart: alwaysnetworks:- testProject_net
  • 在本次实战中我们会使用到缓存(使用sqlc库),因此也进行了redis的配置。如果不想走缓存,可以使用sqlx库,后续根据需求再添加缓存。
  • 在docker-commpose-env.yml中添加如下配置redis

  #redis容器 - Redis containerredis:image: redis:6.2.5container_name: redisports:- 36379:6379environment:# 时区上海 - Time zone Shanghai (Change if needed)TZ: Asia/Shanghaivolumes:# 数据文件 - data files- ./data/redis/data:/data:rwcommand: "redis-server --requirepass G62m50oigInC30sf  --appendonly yes"privileged: truerestart: alwaysnetworks:- testProject_net
  • 在进行复制粘贴的时候需要注意缩进哦!

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

$ docker-compose -f docker-compose-env.yml up -d

Navicate连接数据库

Go-Zero操作数据库

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

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

  • tips:相关服务和表结构在(六)Go-Zero实战之docker开发环境部署 中已经实现,如果本地没有的小伙伴可以先进行(六)的学习和操作哦!
  • 在(六)Go-Zero实战之docker开发环境部署 中我们已经定义了两个RPC接口,接下来我们通过实现这两个register接口展示如何使用gozero操作数据库。

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

  • tips:这一小节的内容在(三)Go-Zero和goctl:解锁微服务开发的神器,快速上手指南 中有过详细的讲解,如果有不清楚的小伙伴可以点击这里进行回顾哦!本节仅进行操作以及效果展示。
  • 脚本如下(放在目录的deploy/script/mysql/genModel.sh下):
#!/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.1
port=33069
dbname=$1
username=root
passwd=PXDN93VRKUm8TeE7
template=../../goctl/1.6.1echo "开始创建库:$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 configimport ("github.com/zeromicro/go-zero/core/stores/cache""github.com/zeromicro/go-zero/zrpc"
)type Config struct {zrpc.RpcServerConfCheckinRpcConf zrpc.RpcClientConfJwtAuth        struct {AccessSecret stringAccessExpire int64}DB struct {DataSource string}Cache cache.CacheConf
}
  • svc下的serviceContext加入如下配置,用于获取mysql连接

package svcimport ("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.ConfigUserModel model.UserModelRedisClient *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配置
#jwtAuth
JwtAuth:AccessSecret: ae0536f9-6450-4606-8e13-5a19ed505da0AccessExpire: 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实战:定制化模板,加速你的微服务开发效率哦!
  • 接下来我们简单看一下模板中对于增删查改方法的实现
  • 插入操作

  • 删除操作

  • 更新操作

  • 查询操作

  • 更多的数据库操作建议可以查看官方文档mysql 代码生成 | go-zero Documentation,本教程更注重于实践操作以及代码实现。

测试与验证

  • 编写完业务后我们启动服务,关于服务启动在(三)Go-Zero和goctl:解锁微服务开发的神器,快速上手指南 中有详细讲解,这里不进行重复讲解。

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

结语

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

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

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

欢迎关注 ❤

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1489416.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

matlab仿真 数字基带传输(上)

(内容源自详解MATLAB/SIMULINK 通信系统建模与仿真 刘学勇编著第六章内容,有兴趣的读者请阅读原书) clear all nsamp10;%每个脉冲信号的抽样点数 s0ones(1,nsamp);%基带脉冲信号,其中s0的信号为1,1,1,1,1,1,1,1,1,1 …

【笔记】缺少DLL文件 Cannot import dll:C\Users\xxx\...\madd.dll

报错 原因 杀毒软件拦截了程序解决:关闭该软件 (1)电脑右下角(↑),找到杀毒软件(我电脑是 联想杀毒Plus) (2)找到 “更改设置” - 选择 “实时扫描” &#…

vue3 使用Mock

官网: http://mockjs.com/ 安装 npm install mockjs -Dsteps1: main.js 文件引入 import /api/mock.jssteps2: src/api/mock.js import Mock from mockjs import homeApi from ./mockData/home /*** 1.拦截的路径:mock拦截了正常NetWork/网络请求,数据正常响应* 2.方法* …

【计算机网络】DHCP实验

一:实验目的 1:深入理解DHCP(动态主机配置协议)的工作原理和数据包交换过程。 2:掌握如何通过命令行释放和重新获取IP地址,并通过抓包软件分析DHCP消息的具体内容。 二:实验仪器设备及软件 硬…

猫头虎 分享已解决Error || pip install 出现 error: subprocess-exited-with-error 错误的解决办法

🐯 猫头虎 分享已解决Error || pip install 出现 error: subprocess-exited-with-error 错误的解决办法 🚀 摘要 🌟 在人工智能领域开发中,我们常常需要使用不同的包管理工具来管理我们的开发环境。作为技术博主猫头虎&#xff…

C++——QT:保姆级教程,从下载到安装到用QT写出第一个程序

登录官网,在官网选择合适的qt版本进行下载 这里选择5.12.9版本 点击exe文件下载,因为服务器在国外,国内不支持,所以可以从我的网盘下载 链接: https://pan.baidu.com/s/1XMILFS1uHTenH3mH_VlPLw 提取码: 1567 --来自百度网盘超级…

【Node.js入门精要】从零开始的开发之旅

说明文档:Node.js 教程_w3cschool 概念 Node.js 是一个开源、跨平台的 JavaScript 运行时环境,基于 Chrome 的 V8 引擎构建,专为构建高性能和可扩展的网络应用程序而设计的服务端语言。它采用事件驱动、非阻塞 I/O 模型,能够处理大…

气膜拳击馆:未来拳击场馆的最佳选择—轻空间

在现代城市化进程中,体育场馆的建设越来越受到关注。传统建筑成本高、施工周期长,并且在环境控制和节能环保方面存在诸多限制。而气膜建筑作为一种新型建筑形式,以其独特的优势和高性价比,逐渐成为各类体育场馆建设的最佳选择。今…

1. 设计原则 C++

1. 设计原则 C++ 1.1 依赖倒置原则(DIP) 高层模块(稳定)不应该依赖于低层模块(变化),两者都应该依赖于抽象(稳定)。如果一个稳定的依赖于一个会变化的(不稳定的),可想而知,也会变得不稳定。 这种就是违背 DIP 。好的设计应该下面这样。 抽象(稳定)不应该依赖…

AI跟踪报道第49期-新加坡内哥谈技术-本周AI新闻: 开源AI王者归来的一周

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

《程序猿入职必会(6) · 返回结果统一封装》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…

unity2D游戏开发08脚本化对象

创建Scriptable Object 在scripts文件夹下创建一个名为Sriptable Objects的文件夹,然后在文件夹里面创建一个名为Item的脚本 using System.Collections; using System.Collections.Generic; using UnityEngine;//[CreateAssetMenu] 是一个属性(Attribute),用于告诉Unity编…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 7月27日,星期六

每天一分钟,知晓天下事! 2024年7月27日 星期六 农历六月廿二 1、 国资委:未来五年中央企业预计安排大规模设备更新改造总投资超3万亿。 2、 我国“巴丹吉林沙漠—沙山湖泊群”“中国黄(渤)海候鸟栖息地(第…

【算法】单向环形链表解决Josephu(约瑟夫)问题

应用场景 n 个小孩标号,逆时针站一圈。从 k 号开始,每一次从当前的小孩逆时针数 m 个,然后让最后这个小孩出列。不断循环上述过程,直到所有小孩出列,由此产生出一个队列编号。 提示 用一个不带头节点的循环链表来处…

电脑为什么会出现“找不到msvcr120.dll无法执行代码”?如何解决msvcr120.dll丢失错误

在使用电脑的过程中不知带大家有没有遇到过“找不到msvcr120.dll无法执行代码”的错误提示的情况,出现这样的情况大家都有什么解决办法可以解决?有什么办法能够帮助大家修复丢失的msvcr120.dll文件。接下来这篇文章就将教大家修复“找不到msvcr120.dll无…

2. SDK分析

1. 概述 恒玄bes2700 sdk属于恒玄面向耳机市场的sdk,主要参考《BES_TWS_Software_Development_User_Manual_v1.2.pdf》 SDK由恒玄提供,版本《best1603_ibrt_anc_20240124_207ba3fb90.tar》 2. 文件树结构 - “apps” mainly stores upper-layer applicat…

NRK2202语音识别芯片在车载分氛围灯的应用方案

一、开发背景 随着汽车从单纯的交通工具向智能化、个性化生活空间的转变,车内环境营造成为了提升驾乘体验的关键一环。氛围灯,不仅能够根据驾驶模式、音乐节奏乃至乘客情绪变换色彩与亮度,更承载着营造温馨、浪漫或激情氛围的重任。然而&…

[Windows CMD] 查看网络配置 ipconfig

ipconfig 是一个网络命令工具,用于显示所有适配器(网络接口)的 IPv4 和 IPv6 配置信息。这个命令在 Windows 操作系统中非常常用,也存在于其他一些基于 IP 的网络系统中,如 macOS 和 Linux(在这些系统中通常…

C++ //练习 15.30 编写你自己的Basket类,用它计算上一个练习中交易记录的总价格。

C Primer(第5版) 练习 15.30 练习 15.30 编写你自己的Basket类,用它计算上一个练习中交易记录的总价格。 环境:Linux Ubuntu(云服务器) 工具:vim 代码块: /********************…

vue3 父组件 props 异步传值,子组件接收不到或接收错误

1. 使用场景 我们在子组件中通常需要调用父组件的数据,此时需要使用 vue3 的 props 进行父子组件通信传值。 2. 问题描述 那么此时问题来了,在使用 props 进行父子组件通信时,因为数据传递是异步的,导致子组件无法成功获取数据…