Documentation
¶
Overview ¶
Package async 提供安全的 goroutine 启动工具。
适用于所有使用此包的后端服务,防止 goroutine panic 导致进程崩溃。
核心特性 ¶
- 自动 recover panic 并记录堆栈
- 支持共享 channel 收集错误(GoSafeWithErrChannel)
- 一行代码替代 go func(){...}()
快速接入 ¶
替代裸 go 关键字:
async.GoSafe(func() {
doSomething()
})
需要收集多个 goroutine 的错误到同一 channel 时:
ch := make(chan error, 10)
async.GoSafeWithErrChannel(ch, func() error {
return doSomething()
})
错误只需日志上报的后台任务:
async.GoSafeWithErr(func() error {
return flushBatch(ctx)
})
携带 context 的安全 goroutine:
async.GoWithContext(ctx, func(ctx context.Context) { doWork(ctx) })
async.GoSafeWithContext(ctx, func(ctx context.Context) error { return doWork(ctx) })
命名后台任务(panic 日志带 task 标签,可按任务聚合告警):
async.GoSafeLabeled("janitor", func() { sweep() })
async.RunSafeLabeled("batch-flush", func() { flush() })
使用场景 ¶
- 后台任务:日志上报、指标采集、缓存预热
- 并发请求:同时调用多个下游服务
- 异步处理:消息发送、文件处理
Panic 处理 ¶
panic 被 recover 后会:
- 记录 panic 信息和完整堆栈到日志
- GoSafeWithErrChannel 会将 panic 转为 error 发送到共享 channel
- 不会影响主 goroutine 的正常运行
为什么使用标准库 log 而非 logx ¶
本包是使用方的 panic 兜底层,必须保持零内部依赖(依赖叶子节点)。 logx 会间接依赖 middleware、ratelimit 等上层包,而这些包又依赖 async, 若 async 反向依赖 logx 将形成导入环。因此本包刻意使用标准库 log。
Index ¶
- func GoSafe(fn func())
- func GoSafeLabeled(task string, fn func())
- func GoSafeWithContext(ctx context.Context, fn func(ctx context.Context) error)
- func GoSafeWithContextLabeled(ctx context.Context, task string, fn func(ctx context.Context))
- func GoSafeWithErr(fn func() error)
- func GoSafeWithErrChannel(ch chan<- error, fn func() error)
- func GoWithContext(ctx context.Context, fn func(ctx context.Context))
- func ReportPanic(r any)
- func RunSafe(fn func())
- func RunSafeErr(fn func() error) (err error)
- func RunSafeLabeled(task string, fn func())
- func RunSafeRet[T any](fn func() (T, error)) (val T, err error)
- func RunSafeRetLabeled[T any](task string, fn func() (T, error)) (val T, err error)
- func RunSafeRetWith[T any](r Runner, fn func() (T, error)) (val T, err error)
- func SetPanicHandler(handler PanicHandler)
- type PanicError
- type PanicHandler
- type Runner
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GoSafeLabeled ¶ added in v0.5.0
func GoSafeLabeled(task string, fn func())
GoSafeLabeled 与 GoSafe 相同,但 panic 汇报带任务归属标签。 后台循环 / 心跳 / 清扫等命名任务用本变体,运维可直接按 task 聚合。
func GoSafeWithContext ¶
GoSafeWithContext 启动一个携带 ctx 的安全 goroutine,fn 返回的 error (含 panic 转换的 error)经 PanicHandler 记录。等价 GoWithContext + 错误上报。
func GoSafeWithContextLabeled ¶ added in v0.5.0
GoSafeWithContextLabeled 启动带 ctx 的安全 goroutine,panic 汇报带任务归属标签。
func GoSafeWithErr ¶
func GoSafeWithErr(fn func() error)
GoSafeWithErr 启动一个带 panic 恢复的 goroutine 执行 fn。 fn 返回的 error(含 panic 转换的 error)经 PanicHandler 记录后丢弃—— 适合"错误只需日志上报"的后台任务;需要收集错误到共享 channel 用 GoSafeWithErrChannel,需要同步等待/级联取消用 concurrency/group。
func GoSafeWithErrChannel ¶
GoSafeWithErrChannel 启动 fn 并把 panic 与 fn 返回值都发送到共享 channel。
用于需要收集多个 goroutine 的错误到同一 channel 的场景(如 concurrency/group)。 调用方需保证 ch 缓冲足够大(建议至少为参与 goroutine 的数量),避免阻塞。 发送始终非阻塞;若 channel 已满或已被调用方关闭,不阻塞、不崩溃, 相关 panic 经 PanicHandler 输出。调用方应避免在还有 goroutine 未返回时关闭 ch。
func GoWithContext ¶
GoWithContext 启动一个携带 ctx 的安全 goroutine(panic 恢复,无错误上报)。 fn 收到的就是调用方传入的 ctx,取消/超时由调用方管理。
func ReportPanic ¶ added in v0.5.0
func ReportPanic(r any)
ReportPanic 将一次「已被调用方 recover 的 panic」上报给全局 PanicHandler, 供自管 recover 的编排原语(如 syncx.FanInErr 逐槽收编)保持与 GoSafe/RunSafe 统一的观测面——handler 注入方(日志/告警)不漏接任何恢复事件。 msg 形如 "panic recovered: <payload>";stack 取当前调用栈。
func RunSafe ¶ added in v0.4.0
func RunSafe(fn func())
RunSafe 在当前 goroutine 同步运行 fn,panic 被 recover 并经 PanicHandler 汇报(不重新 panic)。适合"第三方回调不应打死调用方"的场景,如批量执行器 执行用户回调;需要独立 goroutine 用 GoSafe。
func RunSafeErr ¶ added in v0.6.0
RunSafeErr 同步运行 fn,panic 收编为 error 返回(不再静默)。 适合「panic → 领域 error 透给调用方」场景(如 guardedCall)。 正常返回值原样透传;panic 时额外经 PanicHandler 汇报。
func RunSafeLabeled ¶ added in v0.5.0
func RunSafeLabeled(task string, fn func())
RunSafeLabeled 与 RunSafe 相同,但 panic 汇报带任务归属标签。 msg 形如 "task=janitor: boom",便于按任务维度聚合告警,不依赖堆栈解析。 task 为空时退化为 RunSafe 的消息格式。
func RunSafeRet ¶ added in v0.6.0
RunSafeRet 同步运行返回 (T, error) 的 fn,panic 收编为 error(零值 T)。 调用方能区分「合法零值 + nil」与「panic 失败」。
func RunSafeRetLabeled ¶ added in v0.6.0
RunSafeRetLabeled 同 RunSafeRet,panic 汇报带任务归属标签。
func RunSafeRetWith ¶ added in v0.7.0
RunSafeRetWith 是 Runner 版的 RunSafeRet(方法不能带类型参数, 泛型形态以包级函数提供)。
func SetPanicHandler ¶
func SetPanicHandler(handler PanicHandler)
SetPanicHandler 设置全局 panic 恢复日志处理器。 应在 main.go 初始化阶段调用,注入 logx 等结构化日志实现。
用法:
async.SetPanicHandler(func(msg string, stack []byte) {
logx.Error("goroutine panic", "error", msg, "stack", string(stack))
})
Types ¶
type PanicError ¶ added in v0.7.0
type PanicError struct {
// Value 是 recover() 的原始值。
Value any
// Stack 是 panic 时的调用栈(debug.Stack(),与 PanicHandler 收到的同一份)。
Stack []byte
// Task 是 Labeled 变体的任务标签;非 Labeled 为空。
Task string
}
PanicError 是 panic 收编为 error 的统一载体(#12)。
RunSafeErr / RunSafeRet / RunSafeRetLabeled 的 panic 分支、syncx.FanInErr 的逐槽收编、singleflight.Flight 的 waiter 错误路径均使用本类型——调用方 用 errors.As 即可区分「panic 失败」与「业务错误」,拿到原始 payload 与栈, 再按自己的 logger 补挂领域上下文后决定降级或透传。
Error() 文案与历史实现一致("panic: <Value>";Labeled 变体 "task=<Task>: panic: <Value>"),现有字符串匹配零破坏。
func NewPanicError ¶ added in v0.7.0
func NewPanicError(r any) *PanicError
NewPanicError 供包内其他收编点(syncx.FanInErr 逐槽、singleflight waiter) 构造统一载体;外部消费方一般不需要——错误已经从 RunSafe*/Slot.Err 拿到。
func (*PanicError) Error ¶ added in v0.7.0
func (e *PanicError) Error() string
type PanicHandler ¶
PanicHandler 是 panic 恢复时的日志处理函数。 默认使用标准库 log.Printf。可通过 SetPanicHandler 注入自定义实现(如 logx)。
type Runner ¶ added in v0.7.0
type Runner struct {
// Handler 本实例的 panic 汇报函数;nil 回退全局 PanicHandler。
Handler PanicHandler
}
Runner 携带自己的 PanicHandler 的 GoSafe/RunSafe 家族(#13)。
服务形态消费方继续用包级函数 + SetPanicHandler(进程入口一次); 库形态消费方(被宿主 import,不能动全局)在包级持有一个 Runner, panic 路由到自己的组件 logger,宿主的全局设置不受影响、互不覆盖。 零值 Runner 回退全局 handler(与包级函数行为一致)。
用法:
var runner = async.Runner{Handler: func(msg string, stack []byte) {
logx.Error("agentkit.worker.task_panic", "msg", msg, "stack", string(stack))
}}
runner.GoSafeLabeled("claim", func() { ... })
err := runner.RunSafeErr(func() error { ... })
func (Runner) GoSafe ¶ added in v0.7.0
func (r Runner) GoSafe(fn func())
GoSafe 启动带 panic 恢复的 goroutine(汇报走本实例 handler)。
func (Runner) GoSafeLabeled ¶ added in v0.7.0
GoSafeLabeled 带 task 标签的 GoSafe(msg 形如 "task=janitor: ...")。
func (Runner) GoWithContext ¶ added in v0.7.0
GoWithContext 启动携带 ctx 的安全 goroutine(汇报走本实例 handler)。
func (Runner) RunSafe ¶ added in v0.7.0
func (r Runner) RunSafe(fn func())
RunSafe 同步运行 fn,panic 经本实例 handler 汇报(不重新 panic)。
func (Runner) RunSafeErr ¶ added in v0.7.0
RunSafeErr 同步运行 fn,panic 收编为 *PanicError 返回并经本实例 handler 汇报。