go-zero整合单机版Redis并实现增删改查

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:6379
  Type: node
  Pass: "123456789"
  Tls: false

config.go

config.go文件中新增RedisConf配置信息,如下:

	RedisConf struct {
		Host string
		Type string `json:",default=node,options=node|cluster"`
		Pass string `json:",optional"`
		Tls  bool   `json:",optional"`
	}

servicecontext.go

servicecontext.go文件新增Redis配置信息,完整代码如下:

package svc

import (
	"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.Config
	RedisClient *redis.Redis

	UserModel 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/test
	prefix : /redis/test
)

service admin-api{
	@doc(
		summary : "Redis新增数据"
	)
	@handler RedisAdd
	post /redisAdd(ApiRedisReq)returns(ApiRedisResp)

	@doc(
		summary : "Redis删除数据"
	)
	@handler RedisDelete
	post /redisDelete(ApiRedisReq)returns(ApiRedisResp)

	@doc(
		summary : "Redis修改数据"
	)
	@handler RedisUpdate
	post /redisUpdate(ApiRedisReq)returns(ApiRedisResp)

	@doc(
		summary : "Redis查询数据"
	)
	@handler RedisGet
	get /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("数据转换异常")
	}

	// 添加数据到Redis
	var 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.RedisResp
	err = 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.RedisResp
	err = 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.RedisResp
	err = 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"}}%
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宋发元

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值