mcpField
G
golang-samber-ro

golang-samber-ro

github.com/samber开发3.7k38.5k 次安装5 天前更新
代码仓库

关于 golang-samber-ro

面向 Go 工程师的 samber/ro 响应式流技能,介绍用于异步数据流的泛型、类型安全管道。它涵盖操作符、冷热 Observable、背压、错误传播与资源清理。

主要功能

  1. 01150 多种流操作符
  2. 02类型安全的管道组合
  3. 03冷与热 Observable 及 5 种 Subject
  4. 04背压、错误传播与上下文集成
  5. 0540 多种扩展插件

适用场景

  1. 01处理 WebSocket、定时器或文件监听等持续事件流
  2. 02组合多个异步数据源进行实时数据处理
  3. 03向多个订阅者广播共享事件
  4. 04对流操作配置重试、超时与取消

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-ro

安装后在 Claude Code 中输入/golang-samber-ro确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
references/
operators-guide.md
patterns.md
plugin-ecosystem.md
subjects-guide.md

详细介绍

角色定位: 你是一名 Go 工程师,在数据以异步或无限流动时会选择响应式流。你使用 samber/ro 构建声明式管道,而不是手动连接 goroutine/channel,但也知道何时简单的切片 + samber/lo 就足够了。

思考模式: 设计高级响应式管道,或在冷/热 observable、subject 和组合运算符之间做选择时,要尽可能全面地推理——架构选择错误会导致资源泄漏或事件遗漏。在 Claude Code 中,使用 ultrathink 显式触发扩展思考。

samber/ro — Go 响应式流

ReactiveX 的 Go 实现。以泛型为先、类型安全且可组合的异步数据流管道,支持自动背压、错误传播、上下文集成和资源清理。包含 150 多个运算符、5 种 subject 和 40 多个插件。

官方资源:

本技能并未涵盖所有内容——更多信息请参阅库文档和代码示例:

  • 如需 Go 包文档、符号、版本、导入方和已知漏洞,→ 请参阅 samber/cc-skills-golang@golang-pkg-go-dev 技能(godig),查询 Go 包信息时优先于 Context7。
  • 如需在自己的代码中查找此库的用法(定义、调用位置、诊断信息),→ 请参阅 samber/cc-skills-golang@golang-gopls 技能(gopls)。
  • 对于未在 pkg.go.dev 上索引的文档,Context7 仍可作为备用方案。

为什么选择 samber/ro(流与切片)

对于复杂的异步管道,Go channel + goroutine 会变得难以管理:需要手动关闭 channel,goroutine 生命周期管理冗长,在嵌套 select 之间传播错误也很繁琐,而且没有可组合的运算符。samber/ro 通过声明式、可链式调用的流运算符解决了这些问题。

适用场景:

场景工具原因
转换切片(map、filter、reduce)samber/lo有限、同步、急切求值——无需流带来的额外开销
简单的 goroutine 扇出并处理错误errgroup标准库、轻量,对于有界并发已足够
无限事件流(WebSocket、定时器、文件监视器)samber/ro声明式管道,支持背压、重试、超时和组合
从多个异步源实时丰富数据samber/roCombineLatest/Zip 可组合相关流,无需手动使用 select
多个消费者共享一个源的发布/订阅samber/ro热 observable(Share/Subjects)可原生处理多播

关键区别:lo 与 ro

方面samber/losamber/ro
数据有限切片无限流
执行同步、阻塞异步、非阻塞
求值急切(分配中间切片)惰性(数据到达时逐项处理)
时序即时感知时间(delay、throttle、interval、timeout)
错误模型每次调用返回 (T, error)错误通过管道中的错误通道传播
使用场景集合转换事件驱动、实时、异步管道

安装

go get github.com/samber/ro

核心概念

四个构建模块:

  1. Observable — 随时间发出值的数据源。默认是冷 observable:每个订阅者都会触发一次独立的全新执行
  2. Observer — 包含三个回调的消费者:onNext(T)、onError(error)、onComplete()
  3. Operator — 将一个 observable 转换为另一个 observable 的函数,通过 Pipe 链式调用
  4. Subscription — observable 与 observer 之间的连接。调用 .Wait() 阻塞,或调用 .Unsubscribe() 取消订阅
observable := ro.Pipe2(
    ro.RangeWithInterval(0, 5, 1*time.Second),
    ro.Filter(func(x int) bool { return x%2 == 0 }),
    ro.Map(func(x int) string { return fmt.Sprintf("even-%d", x) }),
)

observable.Subscribe(ro.NewObserver(
    func(s string) { fmt.Println(s) },      // onNext
    func(err error) { log.Println(err) },    // onError
    func() { fmt.Println("Done!") },         // onComplete
))
// Output: "even-0", "even-2", "even-4", "Done!"

// Or collect synchronously:
values, err := ro.Collect(observable)

冷与热可观测对象

冷(默认):每次调用 .Subscribe() 都会启动一个新的独立执行。安全且可预测——默认使用。

热:多个订阅者共享同一次执行。适用于数据源开销较大的情况(WebSocket、数据库轮询),或订阅者必须看到相同事件的情况。

转换方式行为
Share()将冷可观测对象转换为热可观测对象,并采用引用计数。最后一个订阅者取消订阅时会停止执行
ShareReplay(n)与 Share 相同,此外还会缓存最近的 N 个值,供较晚订阅的订阅者接收
Connectable()将冷可观测对象转换为热可观测对象,但会等待显式调用 .Connect()
Subjects原生为热;可直接调用 .Send()、.Error()、.Complete()
Subject构造函数重放行为
PublishSubjectNewPublishSubject[T]()无——较晚订阅的订阅者会错过过往事件
BehaviorSubjectNewBehaviorSubject[T](initial)向新订阅者重放最近的值
ReplaySubjectNewReplaySubject[T](bufferSize)重放最近的 N 个值
AsyncSubjectNewAsyncSubject[T]()仅在完成时发出最后一个值
UnicastSubjectNewUnicastSubject[T](bufferSize)仅允许单个订阅者

有关 subject 详情和热可观测对象模式,请参阅 Subjects Guide。

运算符速查

类别主要运算符用途
创建Just、FromSlice、FromChannel、Range、Interval、Defer、Future从各种数据源创建可观测对象
转换Map、MapErr、FlatMap、Scan、Reduce、GroupBy转换或累积流中的值
筛选Filter、Take、TakeLast、Skip、Distinct、Find、First、Last有选择地发出值
组合Merge、Concat、Zip2–Zip6、CombineLatest2–CombineLatest5、Race合并多个可观测对象
错误Catch、OnErrorReturn、OnErrorResumeNextWith、Retry、RetryWithConfig从错误中恢复
计时Delay、DelayEach、Timeout、ThrottleTime、SampleTime、BufferWithTime控制发出值的时机
副作用Tap/Do、TapOnNext、TapOnError、TapOnComplete在不更改流的情况下进行观察
终结Collect、ToSlice、ToChannel、ToMap将流收集为 Go 类型

使用类型化的 Pipe2、Pipe3……Pipe25,可在运算符链中实现编译时类型安全。无类型的 Pipe 使用 any,会失去类型检查。

完整的运算符目录(含 150 多个运算符及其签名),请参阅 Operators Guide。

常见错误

错误失败原因修正方法
使用 ro.OnNext(),但未提供错误处理程序错误会被静默丢弃——缺陷会隐藏在生产环境中使用 ro.NewObserver(onNext, onError, onComplete),并提供全部 3 个回调
使用无类型的 Pipe(),而非 Pipe2/Pipe3失去编译时类型安全,错误会在运行时出现在类型化的运算符链中使用 Pipe2、Pipe3……Pipe25
忘记在无限流上调用 .Unsubscribe()Goroutine 泄漏——可观测对象会永远运行使用 TakeUntil(signal)、取消 context,或显式调用 Unsubscribe()
在冷可观测对象已足够时仍使用 Share()增加不必要的复杂性,也更难推断生命周期仅在多个使用者需要相同流时才使用热可观测对象
使用 samber/ro 转换有限切片对同步操作而言,流会产生额外开销(Goroutine、订阅)使用 samber/lo——它更简单、更快,且专为切片设计
未传递 context 以支持取消流会忽略关闭信号,导致终止时资源泄漏在管道中串联 ContextWithTimeout 或 ThrowOnContextCancel

最佳实践

  1. 始终处理全部三种事件——使用 NewObserver(onNext, onError, onComplete),而不仅仅是 OnNext。未处理的错误会导致数据悄然丢失
  2. 同步消费时使用 Collect()——当流是有限的且你需要 []T 时,Collect 会阻塞直到流结束,并返回切片和错误
  3. 优先使用类型化的 Pipe 函数——Pipe2、Pipe3...Pipe25 会在编译时捕获类型不匹配。仅在动态运算符链中使用非类型化的 Pipe
  4. 为无限流设置边界——使用 Take(n)、TakeUntil(signal)、Timeout(d) 或取消 context。无界流会导致 goroutine 泄漏
  5. 使用 Tap/Do 实现可观测性——记录日志、跟踪或统计数据流发出的值,而不改变数据流。串联 TapOnError 以监控错误
  6. 简单转换优先使用 samber/lo——如果数据是有限切片,且你需要 Map/Filter/Reduce,请使用 lo。当数据随时间到达、来自多个来源,或需要重试/超时时,再使用 ro

插件生态系统

40 多个插件为 ro 扩展了特定领域的运算符:

类别插件导入路径前缀
编码JSON、CSV、Base64、Gobplugins/encoding/...
网络HTTP、I/O、FSNotifyplugins/http、plugins/io、plugins/fsnotify
调度Cron、ICSplugins/cron、plugins/ics
可观测性Zap、Slog、Zerolog、Logrus、Sentry、Oopsplugins/observability/...、plugins/samber/oops
速率限制Native、Ululeplugins/ratelimit/...
数据Bytes、Strings、Sort、Strconv、Regexp、Templateplugins/bytes、plugins/strings 等
系统Process、Signalplugins/proc、plugins/signal

如需查看包含导入路径和用法示例的完整插件目录,请参阅 插件生态系统。

如需了解真实场景中的响应式模式(重试+超时、WebSocket 扇出、优雅关闭、流组合),请参阅 模式。

如果你在 samber/ro 中遇到错误或意外行为,请在 github.com/samber/ro/issues 提交问题。

交叉引用

  • → 有限切片转换(Map、Filter、Reduce、GroupBy)请参阅 samber/cc-skills-golang@golang-samber-lo 技能——数据已在切片中时使用 lo
  • → 可与 ro 管道组合的单子类型(Option、Result、Either)请参阅 samber/cc-skills-golang@golang-samber-mo 技能
  • → 内存缓存(也可作为 ro 插件使用)请参阅 samber/cc-skills-golang@golang-samber-hot 技能
  • → 当响应式流显得过于复杂时,goroutine/channel 模式请参阅 samber/cc-skills-golang@golang-concurrency 技能
  • → 在生产环境中监控响应式管道请参阅 samber/cc-skills-golang@golang-observability 技能

评论

支持 Markdown