Help us shape the future of Go! Take the 2026 Go Developer Survey

singleflight

package
v0.9.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package singleflight 提供并发请求合并(防击穿)工具。

fork 自 github.com/oekit/concurrency/singleflight(stdlib-only 泛型实现): pkg 是最底层模块(零 oekit 内部依赖),cache.SingleFlightCache 需要它 又不能反向依赖 concurrency,故内部化。concurrency 侧修 bug 时须同步本 fork。

同一个 key 的并发调用只执行一次 fn,其他调用共享结果。 适用于缓存穿透防护、token 刷新、配置加载等场景。

核心特性

  • 基于 sync.Map + close(chan struct{}) 实现,零外部依赖
  • 泛型支持,类型安全
  • race detector 友好
  • panic 安全:fn panic 不会导致等待者死锁

快速接入

sf := singleflight.New[string]()
val, err := sf.Do(ctx, "token:wechat_app", func(ctx context.Context) (string, error) {
    return fetchAccessToken(ctx)
})

原理

调用 Do(key, fn) 时:
 1. sync.Map.LoadOrStore 保证只有一个 goroutine 成为 caller
 2. caller 执行 fn,完成后 close(ready) 广播通知
 3. 其他 goroutine (waiter) 通过 <-ready 等待,读取共享结果
 4. close 提供 happens-before 保证,字段读取无 data race

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Flight

type Flight[T any] struct {
	// contains filtered or unexported fields
}

Flight 对同一个 key 的并发调用只执行一次 fn。 零值可用,无需初始化。

func New

func New[T any]() *Flight[T]

New 创建一个 Flight 实例。

func (*Flight[T]) Do

func (f *Flight[T]) Do(ctx context.Context, key string, fn func(ctx context.Context) (T, error)) (T, error)

Do 执行 fn,同一个 key 的并发调用共享结果。

如果多个 goroutine 同时调用 Do 且 key 相同:

  • 只有第一个 goroutine(caller)实际执行 fn
  • 其他 goroutine(waiter)阻塞等待结果
  • caller 完成后所有 waiter 同时获得返回值

panic 处理(与 golang.org/x/sync/singleflight 语义一致):

  • 若 fn panic,panic 向首个 caller 自然传播(保留原始调用栈)
  • waiter 被唤醒并拿到由 panic 转化的 error(而非零值+nil 的伪成功—— 调用方无法区分"合法零值"与"执行失败",会静默污染下游缓存/状态)
  • map 中的 key 记录会被清理,不会因 panic 残留导致后续调用死锁

func (*Flight[T]) Forget

func (f *Flight[T]) Forget(key string)

Forget 移除指定 key 的进行中调用记录。 之后对该 key 的 Do 调用会发起新的 fn 执行。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL