sync.Once 与 sync.Map
一次性初始化与并发映射
sync.Once 与 sync.Map 是 CoddyKit 上的免费 Go Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。
sync.Once
sync.Once 保证某个函数只运行一次,无论有多少个协程并发调用它。典型用例是单例的延迟初始化。
Once.Do
只有对 Do 的第一次调用会执行该函数;后续调用即使来自不同协程,也不会执行任何操作。
var once sync.Once
var db *Database
func getDB() *Database {
once.Do(func() { db = openDB() })
return db
}Once 不会重置
sync.Once 一旦执行过,就无法重置。如果需要可重置的一次性执行,请使用原子操作或互斥锁手动管理状态。
Once 的恐慌行为
如果传递给 Do 的函数触发恐慌,Do 会被视为已完成,后续调用不会执行任何操作。该恐慌会传播给第一个调用者。
sync.Map 概览
sync.Map 是一种无需外部加锁的并发映射。它针对两种模式进行了优化:(1)只写入一次、读取多次;(2)每个协程使用互不相交的键集合。
sync.Map 方法
主要方法:Store、Load、LoadOrStore、删除、Range。没有泛型类型参数——键和值都是 interface{}。
var m sync.Map
m.Store("key", 42)
v, ok := m.Load("key")
if ok { fmt.Println(v.(int)) }LoadOrStore
LoadOrStore 在键存在时返回已有值,否则存储并返回新值。布尔值表示值是已加载(true)还是已存储(false)。
actual, loaded := m.LoadOrStore("key", "default")
if loaded { fmt.Println("existing:", actual) }Range
Range 会遍历所有键值对,并为每一对调用该函数。返回 false 可停止遍历。
m.Range(func(k, v any) bool {
fmt.Println(k, v)
return true // continue
})何时使用 sync.Map
大多数情况下,优先使用带 Mutex 的普通映射——它更简单,而且通常更快。当性能分析显示存在竞争,或访问模式符合其优化目标时,再使用 sync.Map。
LoadAndDelete
LoadAndDelete 会以原子方式加载值并删除键,同时返回之前的值以及该键是否存在。
v, loaded := m.LoadAndDelete("key")
if loaded { fmt.Println("deleted:", v) }sync.Map 不是泛型的
存储在 sync.Map 中的值是 any。请将 sync.Map 封装在带类型的方法的类型安全结构体中,以避免在代码库中到处进行类型断言。
快速检查
sync.Once 保证什么?
回顾:sync.Once 与 sync.Map
要点:
- sync.Once:让函数恰好运行一次;且不可逆
- sync.Map:针对读操作密集型或键互不相交模式优化的并发映射
- 为保证安全性,请在 sync.Map 外封装带类型的包装器
常见问题解答
「sync.Once 与 sync.Map」课时是免费的吗?
是的 — 「sync.Once 与 sync.Map」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。
「sync.Once 与 sync.Map」这节课中我会学到什么?
一次性初始化与并发映射 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Go Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「sync.Once 与 sync.Map」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Go Academy 课中编写并运行代码吗?
能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- sync.Mutex 与 sync.RWMutex
- sync.WaitGroup
- sync.Once 与 sync.Map
- 竞态检测器与安全模式