当前位置: 首页 > java >正文

GO学习记录八——多文件封装功能+redis使用

这篇打算学习redis使用,在学习过程中顺便梳理了下怎么多文件封装方法,多文件调用。
redis内容有点多,目前只接触了基础api,打算之后完善下再继续补充,先贴出来部分内容是为了防止之后懒得写这个系列了。
一、多文件封装功能函数
1.现在主目录下创建文件目录结构,以此项目为例,我创建了redis_model文件夹(最开始创建的是redis文件夹名称,发现会和官方的redis模块名称冲突提示编译错误),在redis_model文件夹下创建具体的go脚本文件:redis_client.go,redis_hash.go,redis_list.go,redis_set.go,redis_string.go,redis_zset.go。对应redis的客户端和不同的数据结构。
2.具体redis数据结构就不写介绍凑字数了,网上或者AI有一大堆的介绍。直接贴代码内容
redis_client.go

// redis_model/redis_client.go
package redis_modelimport ("context""time""github.com/go-redis/redis/v8"
)var (Client *redis.ClientCtx    = context.Background()
)// InitRedis 初始化 Redis 客户端
func InitRedis(addr, password string, db int) error {Client = redis.NewClient(&redis.Options{Addr:         addr,     // e.g., "localhost:6379"Password:     password, // no password setDB:           db,       // use default DBPoolSize:     10,DialTimeout:  5 * time.Second,ReadTimeout:  3 * time.Second,WriteTimeout: 3 * time.Second,})// 测试连接_, err := Client.Ping(Ctx).Result()return err
}// Close 关闭 Redis 连接
func Close() {_ = Client.Close()
}

redis_hash.go

// redis_model/redis_hash.go
package redis_model// HashSet 设置 hash 字段
func HashSet(key, field, value string) error {return Client.HSet(Ctx, key, field, value).Err()
}// HashMSet 批量设置 hash
func HashMSet(key string, fields map[string]interface{}) error {return Client.HMSet(Ctx, key, fields).Err()
}// HashGet 获取 hash 字段
func HashGet(key, field string) (string, error) {return Client.HGet(Ctx, key, field).Result()
}// HashGetAll 获取所有字段
func HashGetAll(key string) (map[string]string, error) {return Client.HGetAll(Ctx, key).Result()
}// HashDel 删除字段
func HashDel(key string, fields ...string) error {return Client.HDel(Ctx, key, fields...).Err()
}// HashExists 判断字段是否存在
func HashExists(key, field string) (bool, error) {exists, err := Client.HExists(Ctx, key, field).Result()return exists, err
}

redis_list.go

// redis_model/redis_list.go
package redis_model// ListLPush 从左侧插入
func ListLPush(key string, values ...interface{}) error {return Client.LPush(Ctx, key, values...).Err()
}// ListRPush 从右侧插入
func ListRPush(key string, values ...interface{}) error {return Client.RPush(Ctx, key, values...).Err()
}// ListLPop 从左侧弹出
func ListLPop(key string) (string, error) {return Client.LPop(Ctx, key).Result()
}// ListRPop 从右侧弹出
func ListRPop(key string) (string, error) {return Client.RPop(Ctx, key).Result()
}// ListRange 获取范围 [start, stop]
func ListRange(key string, start, stop int64) ([]string, error) {return Client.LRange(Ctx, key, start, stop).Result()
}// ListLen 获取长度
func ListLen(key string) (int64, error) {return Client.LLen(Ctx, key).Result()
}// ListDel 删除整个 list
func ListDel(key string) error {return Client.Del(Ctx, key).Err()
}

redis_set.go

// redis_model/redis_set.go
package redis_model// SetAdd 添加元素
func SetAdd(key string, members ...interface{}) error {return Client.SAdd(Ctx, key, members...).Err()
}// SetMembers 获取所有元素
func SetMembers(key string) ([]string, error) {return Client.SMembers(Ctx, key).Result()
}// SetIsMember 判断是否是成员
func SetIsMember(key string, member interface{}) (bool, error) {exists, err := Client.SIsMember(Ctx, key, member).Result()return exists, err
}// SetRem 删除元素
func SetRem(key string, members ...interface{}) error {return Client.SRem(Ctx, key, members...).Err()
}// SetCard 获取集合大小
func SetCard(key string) (int64, error) {return Client.SCard(Ctx, key).Result()
}// SetPop 随机弹出一个元素
func SetPop(key string) (string, error) {return Client.SPop(Ctx, key).Result()
}

redis_string.go

// redis_model/redis_string.go
package redis_modelimport "time"// StringSet 设置字符串
func StringSet(key, value string, expiration time.Duration) error {return Client.Set(Ctx, key, value, expiration).Err()
}// StringGet 获取字符串
func StringGet(key string) (string, error) {return Client.Get(Ctx, key).Result()
}// StringDel 删除字符串
func StringDel(key string) error {return Client.Del(Ctx, key).Err()
}// StringExpire 设置过期时间
func StringExpire(key string, expiration time.Duration) error {return Client.Expire(Ctx, key, expiration).Err()
}// StringExists 检查是否存在
func StringExists(key string) (bool, error) {count, err := Client.Exists(Ctx, key).Result()return count > 0, err
}

redis_zset.go

// redis_model/redis_zset.go
package redis_modelimport "github.com/go-redis/redis/v8"// ZAdd 添加元素(score, member)
func ZAdd(key string, members ...*redis.Z) error {return Client.ZAdd(Ctx, key, members...).Err()
}// ZRange 获取升序范围
func ZRange(key string, start, stop int64) ([]string, error) {return Client.ZRange(Ctx, key, start, stop).Result()
}// ZRevRange 获取降序范围
func ZRevRange(key string, start, stop int64) ([]string, error) {return Client.ZRevRange(Ctx, key, start, stop).Result()
}// ZRangeWithScores 获取带分数的元素
func ZRangeWithScores(key string, start, stop int64) ([]redis.Z, error) {return Client.ZRangeWithScores(Ctx, key, start, stop).Result()
}// ZScore 获取成员分数
func ZScore(key, member string) (float64, error) {return Client.ZScore(Ctx, key, member).Result()
}// ZRem 删除成员
func ZRem(key string, members ...string) error {var interfaceMembers []interface{}for _, member := range members {interfaceMembers = append(interfaceMembers, member)}return Client.ZRem(Ctx, key, interfaceMembers...).Err()
}// ZCard 获取有序集合大小
func ZCard(key string) (int64, error) {return Client.ZCard(Ctx, key).Result()
}// ZRank 获取升序排名
func ZRank(key, member string) (int64, error) {return Client.ZRank(Ctx, key, member).Result()
}// ZRevRank 获取降序排名
func ZRevRank(key, member string) (int64, error) {return Client.ZRevRank(Ctx, key, member).Result()
}

这里只贴了main方法中的代码,其他部分和之前的一样。

package mainimport ("context""crypto/rand""encoding/base64""encoding/json""fmt""io""log""net/http""os""path/filepath""regexp""strings""sync""time""github.com/gin-gonic/gin""github.com/go-redis/redis/v8""github.com/jackc/pgx/v5""github.com/jackc/pgx/v5/pgxpool"swaggerFiles "github.com/swaggo/files"ginSwagger "github.com/swaggo/gin-swagger"// 注意:替换为你项目的实际路径// _ "your_project/docs" // docs 包,由 swag 生成// 如果 docs 包在根目录,且 main.go 也在根目录,可以这样导入_ "HTTPServices/docs" // 假设 docs 目录在项目根目录下"HTTPServices/redis_model"_ "HTTPServices/redis_model"
)const (tokenLength = 32             // 令牌长度tokenExpiry = 24 * time.Hour // 令牌有效期
)var (validTokens = make(map[string]time.Time) // 有效令牌tokenMutex  sync.Mutex                   // 令牌锁
)type TokenResponse struct {Token   string    `json:"token"`Expires time.Time `json:"expires"`
}var db *pgxpool.Pool// 启动函数
func main() {// 初始化 直接使用文件夹名称作为对象,调用里面的方法if err := redis_model.InitRedis("localhost:6379", "", 0); err != nil {LogError("Redis连接失败:%v", err)} else {LogSuccess("Redis连接成功")}defer redis_model.Close()// String 操作redis_model.StringSet("name", "Alice", 10*time.Second)name, _ := redis_model.StringGet("name")LogInfo("Name:", name)// Hash 操作redis_model.HashSet("user:1001", "name", "Bob")redis_model.HashSet("user:1001", "age", "25")user, _ := redis_model.HashGetAll("user:1001")LogInfo("User:", user)// List 操作redis_model.ListRPush("tasks", "task1", "task2")tasks, _ := redis_model.ListRange("tasks", 0, -1)LogInfo("Tasks:", tasks)// Set 操作redis_model.SetAdd("tags", "go", "redis", "cache")tags, _ := redis_model.SetMembers("tags")LogInfo("Tags:", tags)// ZSet 操作redis_model.ZAdd("leaderboard", &redis.Z{Score: 100, Member: "alice"}, &redis.Z{Score: 90, Member: "bob"})top, _ := redis_model.ZRevRange("leaderboard", 0, -1)LogInfo("Top:", top)// 初始化数据库连接db = InitDB()defer db.Close()// 注册路由RegisterRouter()// 启动 HTTP 服务go func() {StartHTTPServer()}()// 启动 HTTP api测试服务go func() {StartDebugHTTPServer()}()// 阻塞主线程select {}
}

3.main()代码中可以看到如何调用的其他文件中的方法。
1)直接使用文件夹名称“redis_model”作为对象名,就可以直接点出里面的方法了。
2)作为封装,提供给外部调用的方法,go要求方法名首字母必须大写。
3)注意package包的引入内容,redis相关的功能脚本都放在了“redis_model”文件夹下,所以package对应redis_model,而main.go放在根目录下,所以package对应main。
4)在main的import中,添加redis_model的对应路径,“HTTPServices/redis_model”,我的项目工程叫“HTTPServices”。
二、redis学习理解
1.安装也不说了,网上和AI都能查到。
2.作为前端开发出身,了解redis后,我理解它就类似于是把内容存在了程序内存中。就好比做登录授权时,登录成功后,我把用户的功能权限存在了代码内存中,然后依据功能权限去配置前端页面的功能展示。这时保存用户功能权限数据的部分,就相当于redis在后端位置。
我查了下为什么不直接使用内存,而选用redis,给我的答案是redis的性能比直接用代码内存要高,这个我闲的没事的时候会去验证下。
3.redis也相当于一个应用程序,在进程管理器的后台列表也是可以看到redis的服务的。
redis提供了几种数据类型,方便对应不同的业务场景去使用。
4.既然类似直接使用代码内存,那使用代码内存会遇到的问题,redis也会遇到。比如使用数据的时候正好赶上了数据的更改,或者多个客户端同时访问,同时有删除/访问操作。只是这些问题在redis上有它自己的学名,锁/解锁等等,这些是之后我学完要继续补充的,目前代码只是最基本的操作。

http://www.xdnf.cn/news/18755.html

相关文章:

  • Coze用户账号设置修改用户昵称-前端源码
  • Vue 3 defineOptions 完全指南:让组件选项声明更现代化
  • `lock()` 和 `unlock()` 线程同步函数
  • Node.js(1)—— Node.js介绍与入门
  • maven-default-http-blocker (http://0.0.0.0/)
  • 设计模式4-建造者模式
  • 【AI论文】LiveMCP-101:针对支持多主体通信协议(MCP)的智能体在复杂查询场景下的压力测试与故障诊断
  • iptables 防火墙技术详解
  • 【AI编程】如何快速通过AI IDE集成开发工具来生成一个简易留言板系统
  • 使用 HandlerMethodReturnValueHandler 在SpringBoot项目 实现 RESTful API 返回值自动封装,简化开发
  • Linux系统网络管理
  • 积分排行样式
  • 动态住宅代理:跨境电商数据抓取的稳定解决方案
  • 3785定期复盘代码实现设计模式的越识应用
  • Java接口调用第三方接口时的超时处理策略
  • 浅谈为什么尾递归更高效?——从调用栈和汇编的视角
  • 开源零信任本地化部署实战指南:Keycloak + OpenZiti 完整方案
  • 机器学习-朴素贝叶斯
  • 常用的分布式ID设计方案
  • 可信医疗大数据来源、院内数据、病种数据及编程使用方案分析
  • 【MTCNN网络结构记忆卡片】--003nets.py
  • 嵌入式第三十六天(网络编程(TCP))
  • Java的数字计算
  • More Effective C++ 条款06: 区分自增自减操作符的前缀和后缀形式
  • 若依4.7.8(springboot2.5.15)升级到4.8.1(springboot3.3.5)并集成Dubbo3客户端
  • 工程师的自我修养
  • Python JSON数据格式
  • 【数据结构】-4-顺序表(上)
  • 复杂水域场景识别率↑89%!陌讯多模态融合算法在岸边垃圾检测的落地实践
  • CUDA安装,pytorch库安装