0

0

Go语言实现简单缓存功能_Go缓存项目入门

P粉602998670

P粉602998670

发布时间:2026-01-22 13:10:56

|

881人浏览过

|

来源于php中文网

原创

sync.Map 是高并发读多写少场景下实现线程安全缓存的轻量首选,支持 LoadOrStore 等原子操作,但需手动添加 TTL 和惰性过期清理,小规模场景无需第三方库。

go语言实现简单缓存功能_go缓存项目入门

sync.Map 实现线程安全的简单缓存

Go 标准库没有开箱即用的“缓存”类型,但 sync.Map 是最轻量、最常用的选择——它专为高并发读多写少场景设计,避免了全局锁带来的性能瓶颈

直接用 mapsync.RWMutex 也能做,但要自己处理键存在性判断、删除逻辑、零值覆盖等问题;sync.MapLoadOrStoreCompareAndDelete 等方法天然规避了竞态风险。

  • Load 返回 (value, ok),和普通 map 一致,适合查缓存
  • Store 总是覆盖,LoadOrStore 仅在键不存在时才写入,适合初始化默认值
  • 不支持遍历或获取长度——这是有意为之的设计取舍,若需统计大小,得额外维护计数器

给缓存加过期时间:自己封装 time.Now() 判断

标准 sync.Map 不带 TTL(Time-To-Live),必须手动处理。常见做法是在 value 中嵌入过期时间戳,每次 Load 后检查是否过期,过期则 Delete 并返回未命中。

不要用后台 goroutine 定期扫描清理——小规模缓存没必要,且容易引发误删(比如刚写入就扫到了);按需惰性清理更简单可靠。

立即学习go语言免费学习笔记(深入)”;

SUN2008 企业网站管理系统2.0 beta
SUN2008 企业网站管理系统2.0 beta

1、数据调用该功能使界面与程序分离实施变得更加容易,美工无需任何编程基础即可完成数据调用操作。2、交互设计该功能可以方便的为栏目提供个性化性息功能及交互功能,为产品栏目添加产品颜色尺寸等属性或简单的留言和订单功能无需另外开发模块。3、静态生成触发式静态生成。4、友好URL设置网页路径变得更加友好5、多语言设计1)UTF8国际编码; 2)理论上可以承担一个任意多语言的网站版本。6、缓存机制减轻服务器

下载
  • 存储时用 time.Now().Add(ttl) 计算过期时间,和 value 一起存进 sync.Map
  • 读取时先 Load,再比对当前时间与存储的过期时间,time.Now().After(expireTime)
  • 过期后立即 Delete,避免下次再查一遍重复判断
type CacheItem struct {
	Value    interface{}
	ExpireAt time.Time
}

func (c *Cache) Get(key string) (interface{}, bool) {
	if item, ok := c.m.Load(key); ok {
		if ci, ok := item.(CacheItem); ok {
			if time.Now().Before(ci.ExpireAt) {
				return ci.Value, true
			}
			c.m.Delete(key)
		}
	}
	return nil, false
}

为什么不用第三方库如 gocacheristretto

项目刚起步、QPS 不高、缓存条目几百以内时,引入这些库反而增加复杂度:要理解其驱逐策略(LRU/LFU)、配置参数(shards、buffer size)、生命周期管理(Stop/Reset),还可能带来非预期的内存占用

ristretto 虽然高性能,但它的核心价值在百万级 QPS + GB 级缓存场景;而 gocache 抽象层多,底层仍依赖 sync.Mapmap,中间封装掩盖了真实行为,调试时更难定位问题。

  • 如果只是存 token、配置、用户基本信息,手写 50 行以内的缓存足够用
  • 若后续出现内存持续上涨,优先检查是否忘了设 TTL,而不是立刻换库
  • 真正需要替换的信号是:缓存命中率长期低于 60%,且 key 分布明显倾斜(少数 key 占 80% 流量)

测试缓存并发安全性的关键点

光跑单测不等于线程安全。很多 bug 只在高并发下暴露,比如 LoadOrStoreDelete 交错导致短暂脏读,或过期判断和删除之间被其他 goroutine 插入旧值。

go test -race 是底线,但还不够。建议写一个压力测试函数,混合执行 Get/Set/Delete,并断言命中率、无 panic、无重复初始化。

  • 并发写同一 key 时,LoadOrStore 应保证只初始化一次(适合初始化 DB 连接池等)
  • 并发读+过期删除时,确保不会返回已删除的值,也不会 panic(比如类型断言失败)
  • 避免在 Get 中直接返回指针或可变结构体——外部修改会影响缓存内容,应考虑深拷贝或只缓存不可变类型
缓存逻辑看着简单,最容易出问题的地方其实是过期判断和并发写入的组合;别省那几行代码,把时间比较和删除包进同一个原子操作里。

相关专题

更多
登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

6103

2023.09.14

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

810

2023.09.14

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

1063

2023.12.21

token什么意思
token什么意思

token是一种用于表示用户权限、记录交易信息、支付虚拟货币的数字货币。可以用来在特定的网络上进行交易,用来购买或出售特定的虚拟货币,也可以用来支付特定的服务费用。想了解更多token什么意思的相关内容可以访问本专题下面的文章。

1271

2024.03.01

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

197

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

190

2025.07.04

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

482

2023.08.10

Go中Type关键字的用法
Go中Type关键字的用法

Go中Type关键字的用法有定义新的类型别名或者创建新的结构体类型。本专题为大家提供Go相关的文章、下载、课程内容,供大家免费下载体验。

234

2023.09.06

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

1

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号