go-zero整合单机版Redis并实现增删改查
本教程基于go-zero微服务入门教程
,项目工程结构同上一个教程。
go-zero微服务入门教程(点击进入)
本教程主要实现go-zero框架整合单机版Redis,并暴露接口实现对Redis数据的增删改查。
本文源码:https://gitee.com/songfayuan/go-zero-demo (教程源码分支:2.zero整合单机Redis)
准备工作
- 如不熟悉go-zero项目的,请先查看上一篇
go-zero微服务入门教程
。 - 请自行安装好单机版Redis,建议采用docker安装。
rpc新增Redis配置
以下操作在rpc模块执行。
sys.yaml
sys.yaml配置文件新增Redis配置信息,如下:
# Redis配置
RedisConf:Host: 192.168.2.204:6379Type: nodePass: "123456789"Tls: false
config.go
config.go文件中新增RedisConf配置信息,如下:
RedisConf struct {Host stringType string `json:",default=node,options=node|cluster"`Pass string `json:",optional"`Tls bool `json:",optional"`}
servicecontext.go
servicecontext.go文件新增Redis配置信息,完整代码如下:
package svcimport ("github.com/zeromicro/go-zero/core/stores/redis""github.com/zeromicro/go-zero/core/stores/sqlx""go-zero-demo/rpc/model/sysmodel""go-zero-demo/rpc/sys/internal/config"
)type ServiceContext struct {Config config.ConfigRedisClient *redis.RedisUserModel sysmodel.SysUserModel
}func NewServiceContext(c config.Config) *ServiceContext {sqlConn := sqlx.NewMysql(c.Mysql.Datasource)conf := redis.RedisConf{Host: c.RedisConf.Host,Type: c.RedisConf.Type,Pass: c.RedisConf.Pass,Tls: c.RedisConf.Tls,}return &ServiceContext{Config: c,RedisClient: redis.MustNewRedis(conf),UserModel: sysmodel.NewSysUserModel(sqlConn),}
}
编写rpc服务
修改sys.proto文件
新增Redis操作请求的配置,如下:
message RedisReq{string name = 1;string nickName = 2;string password = 3;string email = 4;string key = 5;
}message RedisResp{string name = 1;string nickName = 2;string password = 3;string email = 4;
}service Sys{// redis增删改查rpc RedisAdd(RedisReq)returns(RedisResp);rpc RedisDelete(RedisReq)returns(RedisResp);rpc RedisUpdate(RedisReq)returns(RedisResp);rpc RedisGet(RedisReq)returns(RedisResp);
}
用goctl生成rpc代码
生成方法同上篇文章,自行查看。
编写API Gateway代码
编写api文件
redis.api
在api目录下创建新目录doc/redis,在redis目录下创建redis.api文件。
syntax = "v1"info(title: "Redis操作相关"desc: "Redis操作相关"author: "宋发元"
)type (ApiRedisReq {Name string `json:"name"`NickName string `json:"nickName"`Password string `json:"password,optional"`Email string `json:"email"`}ApiRedisResp {Code int64 `json:"code"`Message string `json:"message"`Data ApiRedisReq `json:"data"`}ApiRedisGetReq {Key string `form:"key"`}
)@server (group : redis/testprefix : /redis/test
)service admin-api{@doc(summary : "Redis新增数据")@handler RedisAddpost /redisAdd(ApiRedisReq)returns(ApiRedisResp)@doc(summary : "Redis删除数据")@handler RedisDeletepost /redisDelete(ApiRedisReq)returns(ApiRedisResp)@doc(summary : "Redis修改数据")@handler RedisUpdatepost /redisUpdate(ApiRedisReq)returns(ApiRedisResp)@doc(summary : "Redis查询数据")@handler RedisGetget /redisGet(ApiRedisGetReq)returns(ApiRedisResp)
}
admin.api
在api/doc/目录下创建admin.api文件。
import "sys/user.api"
import "redis/redis.api"info(title : "Golang学习项目"author: "songfayuan"email: "songfayuan123@qq.com"version: "1.0.0.0"
)
用goctl生成API Gateway代码
生成方法同上篇文章,自行查看。但是此处要基于admin.api文件去生成代码,如果基于redis.api生成,则生成的代码只有redis.api定义的接口代码,其他api文件定义的接口代码不被生成。
修改API Gateway代码调用rpc服务
redisaddlogic.go
修改api/internal/logic/redis/test/redisaddlogic.go
里的RedisAdd
方法,如下:
func (l *RedisAddLogic) RedisAdd(req *types.ApiRedisReq) (resp *types.ApiRedisResp, err error) {addRes, err := l.svcCtx.Sys.RedisAdd(l.ctx, &sysclient.RedisReq{Name: req.Name,NickName: req.NickName,Password: req.Password,Email: req.Email,})if err != nil {resJson, _ := json.Marshal(addRes)logx.WithContext(l.ctx).Errorf("Redis新增数据测试:操作失败,请求参数param = %s,异常信息errMsg = %s", resJson, err.Error())return nil, rpcerror.New(err)}return &types.ApiRedisResp{Code: 200,Message: "操作成功",Data: types.ApiRedisReq{Name: addRes.Name,NickName: addRes.NickName,Password: addRes.Password,Email: addRes.Email,},}, nil
}
redisdeletelogic.go
修改api/internal/logic/redis/test/redisdeletelogic.go
里的RedisDelete
方法,如下:
func (l *RedisDeleteLogic) RedisDelete(req *types.ApiRedisReq) (resp *types.ApiRedisResp, err error) {l.svcCtx.Sys.RedisDelete(l.ctx, &sysclient.RedisReq{})return &types.ApiRedisResp{Code: 200,Message: "操作成功",Data: types.ApiRedisReq{},}, nil
}
redisupdatelogic.go
修改api/internal/logic/redis/test/redisupdatelogic.go
里的RedisUpdate
方法,如下:
func (l *RedisUpdateLogic) RedisUpdate(req *types.ApiRedisReq) (resp *types.ApiRedisResp, err error) {updateRes, err := l.svcCtx.Sys.RedisUpdate(l.ctx, &sysclient.RedisReq{Name: req.Name,NickName: req.NickName,Password: req.Password,Email: req.Email,})if err != nil {resJson, _ := json.Marshal(updateRes)logx.WithContext(l.ctx).Errorf("Redis更新数据测试:操作失败,请求参数param = %s,异常信息errMsg = %s", resJson, err.Error())return nil, rpcerror.New(err)}return &types.ApiRedisResp{Code: 200,Message: "操作成功",Data: types.ApiRedisReq{Name: updateRes.Name,NickName: updateRes.NickName,Password: updateRes.Password,Email: updateRes.Email,},}, nil
}
redisgetlogic.go
修改api/internal/logic/redis/test/redisgetlogic.go
里的RedisGet
方法,如下:
func (l *RedisGetLogic) RedisGet(req *types.ApiRedisGetReq) (resp *types.ApiRedisResp, err error) {param := &sysclient.RedisReq{}copier.Copy(param, req)getRes, err := l.svcCtx.Sys.RedisGet(l.ctx, param)if err != nil {resJson, _ := json.Marshal(getRes)logx.WithContext(l.ctx).Errorf("获取数据测试:操作失败,请求参数param = %s,异常信息errMsg = %s", resJson, err.Error())return nil, rpcerror.New(err)}return &types.ApiRedisResp{Code: 200,Message: "操作成功",Data: types.ApiRedisReq{Name: getRes.Name,NickName: getRes.NickName,Password: getRes.Password,Email: getRes.Email,},}, nil
}
修改rpc代码调用crud代码
redisaddlogic.go
- 修改
rpc/sys/internal/logic/redisaddlogic.go
,如下内容:
// redis增删改查
func (l *RedisAddLogic) RedisAdd(in *sysclient.RedisReq) (*sysclient.RedisResp, error) {if in.Name == "" {return nil, errors.New("账号不能为空")}if in.NickName == "" {return nil, errors.New("姓名不能为空")}if in.Email == "" {return nil, errors.New("邮箱不能为空")}// 将结构体转换为 JSON 字符串jsonString, err := json.Marshal(in)if err != nil {logx.WithContext(l.ctx).Errorf("Redis新增数据测试:数据转换json出错,异常信息errMsg = %s", err.Error())return nil, errors.New("数据转换异常")}// 添加数据到Redisvar key = "songfayuan"addErr := l.svcCtx.RedisClient.Set(key, string(jsonString))if addErr != nil {return nil, errors.New("存储Redis异常")}// 查询Redis的数据getData, err := l.svcCtx.RedisClient.Get(key)// 将字符串数据解码为 RedisResp 结构体var redisResp sysclient.RedisResperr = json.Unmarshal([]byte(getData), &redisResp)if err != nil {logx.WithContext(l.ctx).Errorf("Redis新增数据测试:返回值封装异常,异常信息errMsg = %s", err.Error())return nil, errors.New("返回值封装异常")}return &redisResp, nil
}
redisdeletelogic.go
- 修改
rpc/sys/internal/logic/redisdeletelogic.go
,如下内容:
func (l *RedisDeleteLogic) RedisDelete(in *sysclient.RedisReq) (*sysclient.RedisResp, error) {var key = "songfayuan"res, err := l.svcCtx.RedisClient.Del(key)if err != nil {return nil, errors.New("删除Redis异常")}logx.Infof("删除Redis数据结果:%s", res)return &sysclient.RedisResp{}, nil
}
redisupdatelogic.go
- 修改
rpc/sys/internal/logic/redisupdatelogic.go
,如下内容:
func (l *RedisUpdateLogic) RedisUpdate(in *sysclient.RedisReq) (*sysclient.RedisResp, error) {if in.Name == "" {return nil, errors.New("账号不能为空")}if in.NickName == "" {return nil, errors.New("姓名不能为空")}if in.Email == "" {return nil, errors.New("邮箱不能为空")}// 将结构体数据转为json字符串jsonString, err := json.Marshal(in)if err != nil {logx.WithContext(l.ctx).Errorf("Redis更新数据测试:数据转换json出错,异常信息errMsg = %s", err.Error())return nil, errors.New("数据转换异常")}// 更新数据到Redis,这里的修改,就是设置新值即可key := "songfayuan"editRes := l.svcCtx.RedisClient.Set(key, string(jsonString))if editRes != nil {return nil, errors.New("修改Redis数据异常")}// 查询Redis的数据getData, err := l.svcCtx.RedisClient.Get(key)// 将字符串数据转换为结构体var redisResp sysclient.RedisResperr = json.Unmarshal([]byte(getData), &redisResp)if err != nil {logx.WithContext(l.ctx).Errorf("修改Redis数据测试:返回值封装异常,异常信息errMsg = %s", err.Error())return nil, errors.New("返回值封装异常")}return &redisResp, nil
}
redisgetlogic.go
- 修改
rpc/sys/internal/logic/redisgetlogic.go
,如下内容:
func (l *RedisGetLogic) RedisGet(in *sysclient.RedisReq) (*sysclient.RedisResp, error) {// 查询Redis的数据getData, err := l.svcCtx.RedisClient.Get(in.Key)// 将字符串数据解码为 RedisResp 结构体var redisResp sysclient.RedisResperr = json.Unmarshal([]byte(getData), &redisResp)if err != nil {logx.WithContext(l.ctx).Errorf("Redis新增数据测试:返回值封装异常,异常信息errMsg = %s", err.Error())return nil, errors.New("返回值封装异常")}return &redisResp, nil
}
完整调用演示
最后,在根目录go-zero-demo执行下命令。
go mod tidy
运行rpc服务
运行方法同上篇文章,自行查看。
运行api
运行方法同上篇文章,自行查看。
api调用
以下调用采用curl进行,你也可以用postman调用。
新增接口
songfayuan@MacBook-Pro ~ curl -X POST -H "Content-Type: application/json" -d '{"name":"songfayuan","nickName":"宋发元","email":"1414@qq.com"}' localhost:8888/redis/test/redisAdd{"code":200,"message":"操作成功","data":{"name":"songfayuan","nickName":"宋发元","password":"","email":"1414@qq.com"}}%
删除接口
songfayuan@MacBook-Pro ~ curl -X POST -H "Content-Type: application/json" -d '{"name":"songfayuan","nickName":"宋发元6666","email":"1414@qq.com"}' localhost:8888/redis/test/redisDelete{"code":200,"message":"操作成功","data":{"name":"","nickName":"","password":"","email":""}}%
修改接口
songfayuan@MacBook-Pro ~ curl -X POST -H "Content-Type: application/json" -d '{"name":"songfayuan","nickName":"宋发元6666","email":"1414@qq.com"}' localhost:8888/redis/test/redisUpdate{"code":200,"message":"操作成功","data":{"name":"songfayuan","nickName":"宋发元6666","password":"","email":"1414@qq.com"}}%
查询接口
songfayuan@MacBook-Pro ~ curl "localhost:8888/redis/test/redisGet?key=songfayuan"{"code":200,"message":"操作成功","data":{"name":"songfayuan","nickName":"宋发元6666","password":"","email":"1414@qq.com"}}%