go-zero(三) 数据库操作
go-zero 数据库操作
在本篇文章中,我们将实现一个用户注册和登录的服务。我们将为此构建一个简单而高效的 API,包括请求参数和响应参数的定义。
一、Mysql连接
1. 创建数据库和表
在 MySQL 中创建名为 test_zero
的数据库,并创建`user 表
CREATE TABLE `users` (`id` BIGINT NOT NULL AUTO_INCREMENT,`username` VARCHAR(50) NOT NULL COLLATE 'utf8_general_ci',`password` VARCHAR(255) NOT NULL COLLATE 'utf8_general_ci',`created_at` TIMESTAMP NULL DEFAULT (CURRENT_TIMESTAMP),PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `username` (`username`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
可以看到username
字段被我设置了唯一性即UNIQUE
,这里先解释一下,使用goctl
生成model代码的时候,它会自动帮我们生成增删改查
等方法。
如果字段设置了唯一性,它会自动生成通过这个字段查找数据的方法,后续我希望通过username
去查询和修改用户数据,所以这里设置了一下。
2. 创建API文件
接下来我们根据这个表,创建user.api
文件,
syntax = "v1"type (// 定义注册接口的 json 请求体RegisterRequest {//请求体定义了 Username 和Password 字段, 并且都设置了不能为空Username string `json:"username" validate:"required"` Password string `json:"password" validate:"required"`}// 定义注册接口的 json 响应体RegisterResponse {//响应体 定义类一个Message 用来返回结果Message string `json:"message"`}
)type (// 定义登录接口的 json 请求体LoginRequest {Username string `json:"username" validate:"required"`Password string `json:"password" validate:"required"`}// 定义登录接口的 json 响应体LoginResponse {//正常的业务逻辑,用户登录后会产生一个token,用来记录登录信息Token string `json:"token"`}
)@server (group: user // 生成代码时都会被放到 user 目录下prefix: /v1 //定义路由前缀为 "/v1"
)// 定义 HTTP 服务
// 微服务名称为 user-api,生成的代码目录和配置文件将和 user 值相关
service user-api {// 定义用户注册接口//定义 http.HandleFunc 转换的 go 文件名称及方法@handler RegisterHandler// 请求方法为 post// 路由为 /register // 请求体为 RegisterRequest// 响应体为 RegisterResponse,响应体必须有 returns 关键字修饰post /register (RegisterRequest) returns (RegisterResponse)//用户登录@handler LoginHandlerpost /login (LoginRequest) returns (LoginResponse)
}
这个 API 的结构可以通过注释清晰地理解。在下面这段代码中,我们可以看到请求参数和响应参数之间通过 returns
进行修饰:
post /register (RegisterRequest) returns (RegisterResponse)
需要注意的是,请求参数
和响应参数
并不总是必需的。
例如,在更新数据时,我们可以省略响应体,只保留请求参数:
post /update (UpdateUserInfoReq)
同样,当我们通过 token 获取数据时,也可以省略请求体,而只定义响应参数:
get /getinfo returns (UserInfoResp)
这样的灵活性使得 API 定义更加简洁明了。
3. 生成服务代码和model代码
我们创建一个新的项目,目录设置为user
,使用goctl
通过user.api
生成项目代码:
goctl api go --api user.api --dir ./
下面我们就演示怎么使用goclt
以及sql
生成model
, 在刚刚生成的项目中,在internal
目录下创建一个modle
的文件夹,然后再这个文件夹下面创建user.sql
,把之前的sql语句粘贴进来,然后使用命令:
goctl model mysql ddl --src user.sql --dir ./
当你看到 Done. 输出则代表生成成功了,帮我们生成了下面3个文件。
$ tree
.
├── usermodel.go
├── usermodel_gen.go
└── vars.go
usermodel.go
: 定义数据库表的模型及其业务逻辑。usermodel_gen.go
: 自动生成的代码,包含数据库操作的实现。vars.go
: 全局变量和配置的定义,供各个模块使用。
4.查看model代码
现在我们来具体看下goctl
帮我们生成的model代码,我们先看下usersmodel.go
文件,
它帮我们定义了NewUsersModel
用来返回user表模型
// NewUsersModel returns a model for the database table.
//NewUsersModel 返回数据库表的模型
func NewUsersModel(conn sqlx.SqlConn) UsersModel {return &customUsersModel{defaultUsersModel: newUsersModel(conn),}
}
接着看下usersmodel_gen.go
文件:
帮我们根据数据库自动生成了数据模型
Users struct {Id int64 `db:"id"`Username string `db:"username"`Password string `db:"password"`CreatedAt time.Time `db:"created_at"`}
给usersModel定义了基本的增删改查的接口
usersModel interface {Insert(ctx context.Context, data *Users) (sql.Result, error)FindOne(ctx context.Context, id int64) (*Users, error)FindOneByUsername(ctx context.Context, username string) (*Users, error)Update(ctx context.Context, data *Users) errorDelete(ctx context.Context, id int64) error
}
5.链接数据库
go-zero 提供了一个强大的 sqlx 工具,用于操作数据库。 所有 SQL 相关操作的包在 github.com/zeromicro/go-zero/core/stores/sqlx
在使用 go-zero 框架与数据库交互时,通常会遵循一系列的步骤和逻辑,下面是调用数据库的典型顺序和逻辑:
增加数据库连接配置
打开 etc\user-api.yaml
文件,增加 MySQL 连接字符串:
#定义了一个名为MysqlDB的结构体,并有一个名为DbSource的字符串。
MysqlDB:# 字符串请根据实际配置环境更改DbSource: "root:root@tcp(127.0.0.1:3306)/test_zero"
设置结构体,用来解析配置文件
现在我们需要把这个MysqlDB
这个字段映射到 go-zero的结构体中,打开internal/config/config.go
文件,把代码修改为以下:
type Config struct {rest.RestConfMysqlDb struct{DbSource string `json:"DbSource"`}
}
我们之前提到过,Config 结构体中的字段与 YAML 文件中的字段可以不区分大小写,但必须保持一致,否则会导致解析错误。如果希望使用不同的名称,可以通过 json:
标签指定 YAML 文件中对应的字段名。
把数据库连接注册到服务上下文
go-zero提供了一个快捷的方式可以创建 Mysql 链接,接着我们就可以使用这个连接进行各种数据库操作:
func NewMysql(datasource string, opts ...SqlOption) SqlConn
我们先使用sqlx.NewMysql(c.MysqlDb.DbSource)
创建数据库连接,然后传给NewUsersModel
,初始化UserModel,打开internal/svc/servicecontext.go
文件,把代码修改为:
//ServiceContext 结构体用户封装服务的上下文信息,相当环境初始化type ServiceContext struct {Config config.Config //UserModel: 类型为 model.UsersModel,表示与用户相关的数据库模型//用于处理与用户相关的数据操作(如用户的创建、读取、更新和删除等)UserModel model.UsersModel
}
//NewServiceContext 是ServiceContext 的构造函数
//它接收配置参数并初始化 ServiceContext,确保服务可以访问所需的配置和数据模型
func NewServiceContext(c config.Config) *ServiceContext {return &ServiceContext{Config: c, //把配置信息注册到服务上下文//通过调用 model.NewUsersModel 函数对UserModel 进行初始化//sqlx.NewMysql 是数据库连接,链接字符串为config中的MysqlDb.DbSourceUserModel: model.NewUsersModel(sqlx.NewMysql(c.MysqlDb.DbSource)),}
}
sqlx.NewMysql
是 sqlx 包中的一个函数,通常用于创建一个新的 MySQL 数据库连接,我们可以看下它在go-zero中的代码, 就是传入datasource 字符串,然后返回SqlConn 数据库连接
func NewMysql(datasource string, opts ...SqlOption) SqlConn {opts = append([]SqlOption{withMysqlAcceptable()}, opts...)return NewSqlConn(mysqlDriverName, datasource, opts...)
}
二、CURD演示
1. 实现注册服务(查、赠)
现在我们开始实现注册逻辑
打开internal/logic/user/registerlogic.go
文件,修改代码如下:
func (l *RegisterLogic) Register(req *types.RegisterRequest) (resp *types.RegisterResponse, err error) {// todo: add your logic here and delete this lineuserModel := l.svcCtx.UserModel //从服务上下文获取UserModel //调用FindOneByUsername查询用户数据,判断用户是否已经注册//req.Username 从请求信息中获取 Usernameuser, _ := userModel.FindOneByUsername(l.ctx, req.Username)//如果username不为空说明已经注册if user != nil {//已经存在用户return nil, err}//插入新的数据_, err = userModel.Insert(l.ctx, &model.Users{Username: req.Username,Password: req.Password,CreatedAt: time.Now(),})if err != nil {// 注册失败return nil, err}//返回响应信息return &types.RegisterResponse{Message: "注册成功",}, nil
}
我们先运行程序,测试一下
2.实现登录服务 (查)
现在我们开始实现=登录逻辑
打开internal/logic/user/loginlogic.go
文件,修改代码如下:
func (l *LoginLogic) Login(req *types.LoginRequest) (resp *types.LoginResponse, err error) {// todo: add your logic here and delete this line//因为我们目前还没涉及到jwt鉴权,所以先把token当面message使用userModel := l.svcCtx.UserModeluser, _ := userModel.FindOneByUsername(l.ctx, req.Username)//查询username判断是否有数据if user != nil { //如果有数据,密码是否和数据库匹配if req.Password == user.Password {return &types.LoginResponse{Token: "登录成功",}, nil} else {return &types.LoginResponse{Token: "密码错误",}, nil}} else {return &types.LoginResponse{Token: "用户未注册",}, nil}}
运行项目
相关文章:

go-zero(三) 数据库操作
go-zero 数据库操作 在本篇文章中,我们将实现一个用户注册和登录的服务。我们将为此构建一个简单而高效的 API,包括请求参数和响应参数的定义。 一、Mysql连接 1. 创建数据库和表 在 MySQL 中创建名为 test_zero的数据库,并创建user 表 …...
SQL面试题——间隔连续问题
间隔连续问题 某游戏公司记录的用户每日登录数据如下 +----+----------+ | id| date| +----+----------+ |1001|2021-12-12| |1001|2021-12-13| |1001|2021-12-14| |1001|2021-12-16| |1001|2021-12-19| |1001|2021-12-20| |1002|2021-12-12| |1002|2021-12-16| |1002|…...

vim配置 --> 在创建的普通用户下
在目录/etc/ 下面,有个名为vimrc 的文件,这是系统中公共的vim配置文件对所有用户都有效 我们现在创建一个普通用户 dm 创建好以后,我们退出重新链接 再切换到普通用户下 再输入密码(是不显示的,输入完后,…...

(计算机毕设)基于SpringBoot+Vue的房屋租赁系统的设计与实现
博主可接毕设设计!!! 各种毕业设计源码只要是你有的题目我这里都有源码 摘 要 社会的发展和科学技术的进步,互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。互…...

【含开题报告+文档+PPT+源码】基于SpringBoot的医院药房管理系统
开题报告 在科技迅速发展的今天,各行各业都在积极寻求与现代技术的融合,以提升自身的运营效率和竞争力。医疗行业作为关乎国计民生的关键领域,其信息化建设的步伐尤为迅速。医院药房作为医疗体系中的核心环节,其管理效率和服务质…...

基于SpringBoot的“数码论坛系统设计与实现”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“数码论坛系统设计与实现”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 系统首页界面图 数码板…...

Linux-第2集-打包压缩 zip、tar WindowsLinux互传
欢迎来到Linux第2集,这一集我会非常详细的说明如何在Linux上进行打包压缩操作,以及解压解包 还有最最重要的压缩包的网络传输 毕竟打包压缩不是目的,把文件最终传到指定位置才是目的 由于打包压缩分开讲没有意义,并且它们俩本来…...

项目进度计划表:详细的甘特图的制作步骤
甘特图(Gantt chart),又称为横道图、条状图(Bar chart),是一种用于管理时间和任务活动的工具。 甘特图由亨利劳伦斯甘特(Henry Laurence Gantt)发明,是一种通过条状图来…...

Cargo Rust 的包管理器
Cargo->Rust 的包管理器 Cargi简介Cargo 的主要功能1. 创建项目2. 管理依赖3. 构建项目4. 运行项目5. 测试代码6. 检查代码7. 生成文档8. 发布和分享包 Cargo 的核心文件1. Cargo.toml2. Cargo.lock **Cargo 的生态系统** 常用命令总结Hello, Cargo! 示例 Cargi简介 Cargo …...

【Rust 编程语言工具】rustup-init.exe 安装与使用指南
rustup-init.exe 是用于安装和管理 Rust 编程语言工具链的 Windows 可执行文件。Rust 是一种系统级编程语言,旨在提供安全、并发和高性能的功能。rustup-init.exe 是官方提供的安装器,用于将 Rust 安装到 Windows 操作系统中,并配置相关环境。…...

集群聊天服务器(12)nginx负载均衡器
目录 负载均衡器nginx负载均衡器优势 如何解决集群聊天服务器跨服务器通信问题?nginx的TCP负载均衡配置nginx配置 负载均衡器 目前最多只能支持2w台客户机进行同时聊天 所以要引入集群,多服务器。 但是客户连哪一台服务器呢?客户并不知道哪一…...

数据挖掘英语及概念
分类 classify 上涨或跌 回归 regression 描述具体数值 分类模型评估 1.混淆(误差)矩阵 confusion matrix 2.ROC曲线 receiver operating characteristic curve 接收者操作特征曲线 3.AUC面积 area under curve ROC曲线下与坐标轴围成的面积&#x…...
springboot第82集:消息队列kafka,kafka-map
官网下载链接:https://kafka.[apache].org/downloads 我下载的是[Scala]2.12 - kafka_2.12-3.1.0.tgz kafka只需要解压下载的压缩包就行了,我这里解压的路径是D:\kafka_2.12-3.1.0,kafka的运行需要依赖zookeeper,当前版本已经内置…...

sql server查看当前正在执行的sql
#统计某类sql执行次数,并按总体cpu消耗时间降序排序 with a as ( select er.session_id,db_name(er.database_id) as DBNAME,sy.last_batch AS 最后执行时间, er.cpu_time ,er.total_elapsed_time/1000 as sum_elapsed_time_s, CAST(csql.text AS varchar(8000)) A…...

STM32设计学生宿舍监测控制系统-分享
目录 前言 一、本设计主要实现哪些很“开门”功能? 二、电路设计原理图 电路图采用Altium Designer进行设计: 三、实物设计图 四、程序源代码设计 五、获取资料内容 前言 本项目旨在利用STM32单片机为核心,结合传感器技术、无线通信技…...
HAproxy 详解
一、基本概念 1.1 什么是 HAproxy? HAproxy(High Availability Proxy)是一个开源的高性能负载均衡器和反向代理服务器,它主要用于在网络上分发流量,以提高网站或应用程序的可用性和性能。HAproxy 可以处理大量的并发…...

间接采购管理:主要挑战与实战策略
间接采购支出会悄然消耗掉企业的现金流,即使是管理完善的公司也难以避免。这是因为间接支出不直接关联特定客户、产品或项目,使采购人员难以跟踪。但正确管理间接支出能为企业带来显著收益——前提是要有合适的工具。本文将分享管理间接支出的关键信息与…...
2411rust,正与整128
原文 长期以来,Rust在x86-32和x86-64架构上128位整数的对齐与C语言不一致.最近已解决此问题,但该修复带来了一些值得注意的效果. 作为用户,除非如下,否则不用担心: 1,假设i128/u128对齐,而不是用align_of 2,忽略improper_ctypes*检查,并在FFI中使用这些类. 除x86-32和x86-64…...

将 HTML 转换为 JSX:JSX 和 JSX 规则
JSX 是 JavaScript 的语法扩展。您可以在 JavaScript 文件中编写 HTML 格式。 它基于 Web、Html、Css 和 JavaScript。Web 开发人员将页面内容分别编写为 Html 文件,将设计编写为 Css 文件,将逻辑编写为 JavaScript 文件。 须知 : JSX 是一个…...

将 FastAPI 部署到生产服务器(一套 全)
将 FastAPI 部署到生产服务器(全) 文章目录 将 FastAPI 部署到生产服务器(全)一、前言二、Fastapi项目 生产环境配置1. 准备环境2. 编写 FastAPI 应用3. 使用 Uvicorn 运行应用4. 配置生产级服务器 Gunicorn4.1 配置 Gunicorn 和 …...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...
React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?
系列回顾: 在上一篇《React核心概念:State是什么?》中,我们学习了如何使用useState让一个组件拥有自己的内部数据(State),并通过一个计数器案例,实现了组件的自我更新。这很棒&#…...