[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CFMFGYE7716NCGYFSNE0V5":3,"skill-same:01M6CFMFGYE7716NCGYFSNE0V5":121},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":49,"linkOnly":50,"markdownContent":51,"markdownBody":52,"frontMatter":53,"refName":69,"commitSha":70,"skillDirectory":71,"forksCount":72,"repositoryHtmlUrl":73,"repositoryHomepageUrl":6,"ownerHtmlUrl":74,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":75,"install":76,"resources":88},"01M6CFMFGYE7716NCGYFSNE0V5","golang-samber-ro",null,"Reactive streams and event-driven programming in Golang using samber\u002Fro — ReactiveX implementation with 150+ type-safe operators, cold\u002Fhot observables, 5 subject types (Publish, Behavior, Replay, Async, Unicast), declarative pipelines via Pipe, 40+ plugins (HTTP, cron, fsnotify, JSON, logging), automatic backpressure, error propagation, and Go context integration. Apply when using or adopting samber\u002Fro, when the codebase imports github.com\u002Fsamber\u002Fro, or when building asynchronous event-driven pipelines, real-time data processing, streams, or reactive architectures in Go. Not for finite slice transforms (→ See `golang-samber-lo` skill).","rockcookies\u002Fskills","rockcookies","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F3498265?v=4","01M6CF9C16X3SDSKZX6ANH7HQM","Jacob He","01M6CF9C53JP821FCW6R9B00AJ",1,"MIT","https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fsamber-golang\u002Fgolang-samber-ro\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],"golang samber ro","golang","Bash","cc","context7","context","edit","write","read","projects","gopls","MCP","data","publish","asynchronous","library","git","code","go","safe","2026-11-10 10:12:30",false,"---\nname: golang-samber-ro\ndescription: >-\n  Reactive streams and event-driven programming in Golang using samber\u002Fro —\n  ReactiveX implementation with 150+ type-safe operators, cold\u002Fhot observables,\n  5 subject types (Publish, Behavior, Replay, Async, Unicast), declarative\n  pipelines via Pipe, 40+ plugins (HTTP, cron, fsnotify, JSON, logging),\n  automatic backpressure, error propagation, and Go context integration. Apply\n  when using or adopting samber\u002Fro, when the codebase imports\n  github.com\u002Fsamber\u002Fro, or when building asynchronous event-driven pipelines,\n  real-time data processing, streams, or reactive architectures in Go. Not for\n  finite slice transforms (→ See `golang-samber-lo` skill).\nuser-invocable: true\nlicense: MIT\ncompatibility: >-\n  Designed for Claude Code, Codex or similar harness, and for projects using\n  Golang.\nmetadata:\n  author: samber\n  version: 1.2.0\n  openclaw:\n    emoji: ?\n    homepage: https:\u002F\u002Fgithub.com\u002Fsamber\u002Fcc-skills-golang\n    requires:\n      bins:\n        - go\n    install: []\n    skill-library-version: 0.3.0\nallowed-tools: >-\n  Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent\n  mcp__context7__resolve-library-id mcp__context7__query-docs AskUserQuestion\n  Bash(godig:*) Bash(gopls:*) LSP mcp__gopls__*\npaths:\n  - '**\u002F*.go'\n---\n\n**Persona:** You are a Go engineer who reaches for reactive streams when data flows asynchronously or infinitely. You use samber\u002Fro to build declarative pipelines instead of manual goroutine\u002Fchannel wiring, but you know when a simple slice + samber\u002Flo is enough.\n\n**Thinking mode:** Reason as thoroughly as possible when designing advanced reactive pipelines or choosing between cold\u002Fhot observables, subjects, and combining operators — wrong architecture leads to resource leaks or missed events. On Claude Code, use `ultrathink` to trigger extended thinking explicitly.\n\n# samber\u002Fro — Reactive Streams for Go\n\nGo implementation of [ReactiveX](https:\u002F\u002Freactivex.io\u002F). Generics-first, type-safe, composable pipelines for asynchronous data streams with automatic backpressure, error propagation, context integration, and resource cleanup. 150+ operators, 5 subject types, 40+ plugins.\n\n**Official Resources:**\n\n- [github.com\u002Fsamber\u002Fro](https:\u002F\u002Fgithub.com\u002Fsamber\u002Fro)\n- [ro.samber.dev](https:\u002F\u002Fro.samber.dev)\n- [pkg.go.dev\u002Fgithub.com\u002Fsamber\u002Fro](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fsamber\u002Fro)\n\nThis skill is not exhaustive. Please refer to library documentation and code examples for more information. For Go package docs, symbols, versions, importers, and known vulnerabilities, → See `golang-pkg-go-dev` skill (`godig`) — prefer it over Context7 for Go package facts. To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See `golang-gopls` skill (`gopls`). Context7 remains a fallback for docs not indexed on pkg.go.dev.\n\n## Why samber\u002Fro (Streams vs Slices)\n\nGo channels + goroutines become unwieldy for complex async pipelines: manual channel closures, verbose goroutine lifecycle, error propagation across nested selects, and no composable operators. `samber\u002Fro` solves this with declarative, chainable stream operators.\n\n**When to use which tool:**\n\n| Scenario | Tool | Why |\n| --- | --- | --- |\n| Transform a slice (map, filter, reduce) | `samber\u002Flo` | Finite, synchronous, eager — no stream overhead needed |\n| Simple goroutine fan-out with error handling | `errgroup` | Standard lib, lightweight, sufficient for bounded concurrency |\n| Infinite event stream (WebSocket, tickers, file watcher) | `samber\u002Fro` | Declarative pipeline with backpressure, retry, timeout, combine |\n| Real-time data enrichment from multiple async sources | `samber\u002Fro` | CombineLatest\u002FZip compose dependent streams without manual select |\n| Pub\u002Fsub with multiple consumers sharing one source | `samber\u002Fro` | Hot observables (Share\u002FSubjects) handle multicast natively |\n\n**Key differences: lo vs ro**\n\n| Aspect | `samber\u002Flo` | `samber\u002Fro` |\n| --- | --- | --- |\n| Data | Finite slices | Infinite streams |\n| Execution | Synchronous, blocking | Asynchronous, non-blocking |\n| Evaluation | Eager (allocates intermediate slices) | Lazy (processes items as they arrive) |\n| Timing | Immediate | Time-aware (delay, throttle, interval, timeout) |\n| Error model | Return `(T, error)` per call | Error channel propagates through pipeline |\n| Use case | Collection transforms | Event-driven, real-time, async pipelines |\n\n## Installation\n\n```bash\ngo get github.com\u002Fsamber\u002Fro\n```\n\n## Core Concepts\n\nFour building blocks:\n\n1. **Observable** — a data source that emits values over time. Cold by default: each subscriber triggers independent execution from scratch\n2. **Observer** — a consumer with three callbacks: `onNext(T)`, `onError(error)`, `onComplete()`\n3. **Operator** — a function that transforms an observable into another observable, chained via `Pipe`\n4. **Subscription** — the connection between observable and observer. Call `.Wait()` to block or `.Unsubscribe()` to cancel\n\n```go\nobservable := ro.Pipe2(\n    ro.RangeWithInterval(0, 5, 1*time.Second),\n    ro.Filter(func(x int) bool { return x%2 == 0 }),\n    ro.Map(func(x int) string { return fmt.Sprintf(\"even-%d\", x) }),\n)\n\nobservable.Subscribe(ro.NewObserver(\n    func(s string) { fmt.Println(s) },      \u002F\u002F onNext\n    func(err error) { log.Println(err) },    \u002F\u002F onError\n    func() { fmt.Println(\"Done!\") },         \u002F\u002F onComplete\n))\n\u002F\u002F Output: \"even-0\", \"even-2\", \"even-4\", \"Done!\"\n\n\u002F\u002F Or collect synchronously:\nvalues, err := ro.Collect(observable)\n```\n\n## Cold vs Hot Observables\n\n**Cold** (default): each `.Subscribe()` starts a new independent execution. Safe and predictable — use by default.\n\n**Hot**: multiple subscribers share a single execution. Use when the source is expensive (WebSocket, DB poll) or subscribers must see the same events.\n\n| Convert with | Behavior |\n| --- | --- |\n| `Share()` | Cold → hot with reference counting. Last unsubscribe tears down |\n| `ShareReplay(n)` | Same as Share + buffers last N values for late subscribers |\n| `Connectable()` | Cold → hot, but waits for explicit `.Connect()` call |\n| Subjects | Natively hot — call `.Send()`, `.Error()`, `.Complete()` directly |\n\n| Subject | Constructor | Replay behavior |\n| --- | --- | --- |\n| `PublishSubject` | `NewPublishSubject[T]()` | None — late subscribers miss past events |\n| `BehaviorSubject` | `NewBehaviorSubject[T](initial)` | Replays last value to new subscribers |\n| `ReplaySubject` | `NewReplaySubject[T](bufferSize)` | Replays last N values |\n| `AsyncSubject` | `NewAsyncSubject[T]()` | Emits only last value, only on complete |\n| `UnicastSubject` | `NewUnicastSubject[T](bufferSize)` | Single subscriber only |\n\nFor subject details and hot observable patterns, see [Subjects Guide](.\u002Freferences\u002Fsubjects-guide.md).\n\n## Operator Quick Reference\n\n| Category | Key operators | Purpose |\n| --- | --- | --- |\n| Creation | `Just`, `FromSlice`, `FromChannel`, `Range`, `Interval`, `Defer`, `Future` | Create observables from various sources |\n| Transform | `Map`, `MapErr`, `FlatMap`, `Scan`, `Reduce`, `GroupBy` | Transform or accumulate stream values |\n| Filter | `Filter`, `Take`, `TakeLast`, `Skip`, `Distinct`, `Find`, `First`, `Last` | Selectively emit values |\n| Combine | `Merge`, `Concat`, `Zip2`–`Zip6`, `CombineLatest2`–`CombineLatest5`, `Race` | Merge multiple observables |\n| Error | `Catch`, `OnErrorReturn`, `OnErrorResumeNextWith`, `Retry`, `RetryWithConfig` | Recover from errors |\n| Timing | `Delay`, `DelayEach`, `Timeout`, `ThrottleTime`, `SampleTime`, `BufferWithTime` | Control emission timing |\n| Side effect | `Tap`\u002F`Do`, `TapOnNext`, `TapOnError`, `TapOnComplete` | Observe without altering stream |\n| Terminal | `Collect`, `ToSlice`, `ToChannel`, `ToMap` | Consume stream into Go types |\n\nUse typed `Pipe2`, `Pipe3` ... `Pipe25` for compile-time type safety across operator chains. The untyped `Pipe` uses `any` and loses type checking.\n\nFor the complete operator catalog (150+ operators with signatures), see [Operators Guide](.\u002Freferences\u002Foperators-guide.md).\n\n## Common Mistakes\n\n| Mistake | Why it fails | Fix |\n| --- | --- | --- |\n| Using `ro.OnNext()` without error handler | Errors are silently dropped — bugs hide in production | Use `ro.NewObserver(onNext, onError, onComplete)` with all 3 callbacks |\n| Using untyped `Pipe()` instead of `Pipe2`\u002F`Pipe3` | Loses compile-time type safety, errors surface at runtime | Use `Pipe2`, `Pipe3`...`Pipe25` for typed operator chains |\n| Forgetting `.Unsubscribe()` on infinite streams | Goroutine leak — the observable runs forever | Use `TakeUntil(signal)`, context cancellation, or explicit `Unsubscribe()` |\n| Using `Share()` when cold is sufficient | Unnecessary complexity, harder to reason about lifecycle | Use hot observables only when multiple consumers need the same stream |\n| Using `samber\u002Fro` for finite slice transforms | Stream overhead (goroutines, subscriptions) for a synchronous operation | Use `samber\u002Flo` — it's simpler, faster, and purpose-built for slices |\n| Not propagating context for cancellation | Streams ignore shutdown signals, causing resource leaks on termination | Chain `ContextWithTimeout` or `ThrowOnContextCancel` in the pipeline |\n\n## Best Practices\n\n1. **Always handle all three events** — use `NewObserver(onNext, onError, onComplete)`, not just `OnNext`. Unhandled errors cause silent data loss\n2. **Use `Collect()` for synchronous consumption** — when the stream is finite and you need `[]T`, `Collect` blocks until complete and returns the slice + error\n3. **Prefer typed Pipe functions** — `Pipe2`, `Pipe3`...`Pipe25` catch type mismatches at compile time. Reserve untyped `Pipe` for dynamic operator chains\n4. **Bound infinite streams** — use `Take(n)`, `TakeUntil(signal)`, `Timeout(d)`, or context cancellation. Unbounded streams leak goroutines\n5. **Use `Tap`\u002F`Do` for observability** — log, trace, or meter emissions without altering the stream. Chain `TapOnError` for error monitoring\n6. **Prefer `samber\u002Flo` for simple transforms** — if the data is a finite slice and you need Map\u002FFilter\u002FReduce, use `lo`. Reach for `ro` when data arrives over time, from multiple sources, or needs retry\u002Ftimeout\u002Fbackpressure\n\n## Plugin Ecosystem\n\n40+ plugins extend ro with domain-specific operators:\n\n| Category | Plugins | Import path prefix |\n| --- | --- | --- |\n| Encoding | JSON, CSV, Base64, Gob | `plugins\u002Fencoding\u002F...` |\n| Network | HTTP, I\u002FO, FSNotify | `plugins\u002Fhttp`, `plugins\u002Fio`, `plugins\u002Ffsnotify` |\n| Scheduling | Cron, ICS | `plugins\u002Fcron`, `plugins\u002Fics` |\n| Observability | Zap, Slog, Zerolog, Logrus, Sentry, Oops | `plugins\u002Fobservability\u002F...`, `plugins\u002Fsamber\u002Foops` |\n| Rate limiting | Native, Ulule | `plugins\u002Fratelimit\u002F...` |\n| Data | Bytes, Strings, Sort, Strconv, Regexp, Template | `plugins\u002Fbytes`, `plugins\u002Fstrings`, etc. |\n| System | Process, Signal | `plugins\u002Fproc`, `plugins\u002Fsignal` |\n\nFor the full plugin catalog with import paths and usage examples, see [Plugin Ecosystem](.\u002Freferences\u002Fplugin-ecosystem.md).\n\nFor real-world reactive patterns (retry+timeout, WebSocket fan-out, graceful shutdown, stream combination), see [Patterns](.\u002Freferences\u002Fpatterns.md).\n\nIf you encounter a bug or unexpected behavior in samber\u002Fro, open an issue at [github.com\u002Fsamber\u002Fro\u002Fissues](https:\u002F\u002Fgithub.com\u002Fsamber\u002Fro\u002Fissues).\n\n## Cross-References\n\n- → See `golang-samber-lo` skill for finite slice transforms (Map, Filter, Reduce, GroupBy) — use lo when data is already in a slice\n- → See `golang-samber-mo` skill for monadic types (Option, Result, Either) that compose with ro pipelines\n- → See `golang-samber-hot` skill for in-memory caching (also available as an ro plugin)\n- → See `golang-concurrency` skill for goroutine\u002Fchannel patterns when reactive streams are overkill\n- → See `golang-observability` skill for monitoring reactive pipelines in production\n","**Persona:** You are a Go engineer who reaches for reactive streams when data flows asynchronously or infinitely. You use samber\u002Fro to build declarative pipelines instead of manual goroutine\u002Fchannel wiring, but you know when a simple slice + samber\u002Flo is enough.\n\n**Thinking mode:** Reason as thoroughly as possible when designing advanced reactive pipelines or choosing between cold\u002Fhot observables, subjects, and combining operators — wrong architecture leads to resource leaks or missed events. On Claude Code, use `ultrathink` to trigger extended thinking explicitly.\n\n# samber\u002Fro — Reactive Streams for Go\n\nGo implementation of [ReactiveX](https:\u002F\u002Freactivex.io\u002F). Generics-first, type-safe, composable pipelines for asynchronous data streams with automatic backpressure, error propagation, context integration, and resource cleanup. 150+ operators, 5 subject types, 40+ plugins.\n\n**Official Resources:**\n\n- [github.com\u002Fsamber\u002Fro](https:\u002F\u002Fgithub.com\u002Fsamber\u002Fro)\n- [ro.samber.dev](https:\u002F\u002Fro.samber.dev)\n- [pkg.go.dev\u002Fgithub.com\u002Fsamber\u002Fro](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fsamber\u002Fro)\n\nThis skill is not exhaustive. Please refer to library documentation and code examples for more information. For Go package docs, symbols, versions, importers, and known vulnerabilities, → See `golang-pkg-go-dev` skill (`godig`) — prefer it over Context7 for Go package facts. To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See `golang-gopls` skill (`gopls`). Context7 remains a fallback for docs not indexed on pkg.go.dev.\n\n## Why samber\u002Fro (Streams vs Slices)\n\nGo channels + goroutines become unwieldy for complex async pipelines: manual channel closures, verbose goroutine lifecycle, error propagation across nested selects, and no composable operators. `samber\u002Fro` solves this with declarative, chainable stream operators.\n\n**When to use which tool:**\n\n| Scenario | Tool | Why |\n| --- | --- | --- |\n| Transform a slice (map, filter, reduce) | `samber\u002Flo` | Finite, synchronous, eager — no stream overhead needed |\n| Simple goroutine fan-out with error handling | `errgroup` | Standard lib, lightweight, sufficient for bounded concurrency |\n| Infinite event stream (WebSocket, tickers, file watcher) | `samber\u002Fro` | Declarative pipeline with backpressure, retry, timeout, combine |\n| Real-time data enrichment from multiple async sources | `samber\u002Fro` | CombineLatest\u002FZip compose dependent streams without manual select |\n| Pub\u002Fsub with multiple consumers sharing one source | `samber\u002Fro` | Hot observables (Share\u002FSubjects) handle multicast natively |\n\n**Key differences: lo vs ro**\n\n| Aspect | `samber\u002Flo` | `samber\u002Fro` |\n| --- | --- | --- |\n| Data | Finite slices | Infinite streams |\n| Execution | Synchronous, blocking | Asynchronous, non-blocking |\n| Evaluation | Eager (allocates intermediate slices) | Lazy (processes items as they arrive) |\n| Timing | Immediate | Time-aware (delay, throttle, interval, timeout) |\n| Error model | Return `(T, error)` per call | Error channel propagates through pipeline |\n| Use case | Collection transforms | Event-driven, real-time, async pipelines |\n\n## Installation\n\n```bash\ngo get github.com\u002Fsamber\u002Fro\n```\n\n## Core Concepts\n\nFour building blocks:\n\n1. **Observable** — a data source that emits values over time. Cold by default: each subscriber triggers independent execution from scratch\n2. **Observer** — a consumer with three callbacks: `onNext(T)`, `onError(error)`, `onComplete()`\n3. **Operator** — a function that transforms an observable into another observable, chained via `Pipe`\n4. **Subscription** — the connection between observable and observer. Call `.Wait()` to block or `.Unsubscribe()` to cancel\n\n```go\nobservable := ro.Pipe2(\n    ro.RangeWithInterval(0, 5, 1*time.Second),\n    ro.Filter(func(x int) bool { return x%2 == 0 }),\n    ro.Map(func(x int) string { return fmt.Sprintf(\"even-%d\", x) }),\n)\n\nobservable.Subscribe(ro.NewObserver(\n    func(s string) { fmt.Println(s) },      \u002F\u002F onNext\n    func(err error) { log.Println(err) },    \u002F\u002F onError\n    func() { fmt.Println(\"Done!\") },         \u002F\u002F onComplete\n))\n\u002F\u002F Output: \"even-0\", \"even-2\", \"even-4\", \"Done!\"\n\n\u002F\u002F Or collect synchronously:\nvalues, err := ro.Collect(observable)\n```\n\n## Cold vs Hot Observables\n\n**Cold** (default): each `.Subscribe()` starts a new independent execution. Safe and predictable — use by default.\n\n**Hot**: multiple subscribers share a single execution. Use when the source is expensive (WebSocket, DB poll) or subscribers must see the same events.\n\n| Convert with | Behavior |\n| --- | --- |\n| `Share()` | Cold → hot with reference counting. Last unsubscribe tears down |\n| `ShareReplay(n)` | Same as Share + buffers last N values for late subscribers |\n| `Connectable()` | Cold → hot, but waits for explicit `.Connect()` call |\n| Subjects | Natively hot — call `.Send()`, `.Error()`, `.Complete()` directly |\n\n| Subject | Constructor | Replay behavior |\n| --- | --- | --- |\n| `PublishSubject` | `NewPublishSubject[T]()` | None — late subscribers miss past events |\n| `BehaviorSubject` | `NewBehaviorSubject[T](initial)` | Replays last value to new subscribers |\n| `ReplaySubject` | `NewReplaySubject[T](bufferSize)` | Replays last N values |\n| `AsyncSubject` | `NewAsyncSubject[T]()` | Emits only last value, only on complete |\n| `UnicastSubject` | `NewUnicastSubject[T](bufferSize)` | Single subscriber only |\n\nFor subject details and hot observable patterns, see [Subjects Guide](.\u002Freferences\u002Fsubjects-guide.md).\n\n## Operator Quick Reference\n\n| Category | Key operators | Purpose |\n| --- | --- | --- |\n| Creation | `Just`, `FromSlice`, `FromChannel`, `Range`, `Interval`, `Defer`, `Future` | Create observables from various sources |\n| Transform | `Map`, `MapErr`, `FlatMap`, `Scan`, `Reduce`, `GroupBy` | Transform or accumulate stream values |\n| Filter | `Filter`, `Take`, `TakeLast`, `Skip`, `Distinct`, `Find`, `First`, `Last` | Selectively emit values |\n| Combine | `Merge`, `Concat`, `Zip2`–`Zip6`, `CombineLatest2`–`CombineLatest5`, `Race` | Merge multiple observables |\n| Error | `Catch`, `OnErrorReturn`, `OnErrorResumeNextWith`, `Retry`, `RetryWithConfig` | Recover from errors |\n| Timing | `Delay`, `DelayEach`, `Timeout`, `ThrottleTime`, `SampleTime`, `BufferWithTime` | Control emission timing |\n| Side effect | `Tap`\u002F`Do`, `TapOnNext`, `TapOnError`, `TapOnComplete` | Observe without altering stream |\n| Terminal | `Collect`, `ToSlice`, `ToChannel`, `ToMap` | Consume stream into Go types |\n\nUse typed `Pipe2`, `Pipe3` ... `Pipe25` for compile-time type safety across operator chains. The untyped `Pipe` uses `any` and loses type checking.\n\nFor the complete operator catalog (150+ operators with signatures), see [Operators Guide](.\u002Freferences\u002Foperators-guide.md).\n\n## Common Mistakes\n\n| Mistake | Why it fails | Fix |\n| --- | --- | --- |\n| Using `ro.OnNext()` without error handler | Errors are silently dropped — bugs hide in production | Use `ro.NewObserver(onNext, onError, onComplete)` with all 3 callbacks |\n| Using untyped `Pipe()` instead of `Pipe2`\u002F`Pipe3` | Loses compile-time type safety, errors surface at runtime | Use `Pipe2`, `Pipe3`...`Pipe25` for typed operator chains |\n| Forgetting `.Unsubscribe()` on infinite streams | Goroutine leak — the observable runs forever | Use `TakeUntil(signal)`, context cancellation, or explicit `Unsubscribe()` |\n| Using `Share()` when cold is sufficient | Unnecessary complexity, harder to reason about lifecycle | Use hot observables only when multiple consumers need the same stream |\n| Using `samber\u002Fro` for finite slice transforms | Stream overhead (goroutines, subscriptions) for a synchronous operation | Use `samber\u002Flo` — it's simpler, faster, and purpose-built for slices |\n| Not propagating context for cancellation | Streams ignore shutdown signals, causing resource leaks on termination | Chain `ContextWithTimeout` or `ThrowOnContextCancel` in the pipeline |\n\n## Best Practices\n\n1. **Always handle all three events** — use `NewObserver(onNext, onError, onComplete)`, not just `OnNext`. Unhandled errors cause silent data loss\n2. **Use `Collect()` for synchronous consumption** — when the stream is finite and you need `[]T`, `Collect` blocks until complete and returns the slice + error\n3. **Prefer typed Pipe functions** — `Pipe2`, `Pipe3`...`Pipe25` catch type mismatches at compile time. Reserve untyped `Pipe` for dynamic operator chains\n4. **Bound infinite streams** — use `Take(n)`, `TakeUntil(signal)`, `Timeout(d)`, or context cancellation. Unbounded streams leak goroutines\n5. **Use `Tap`\u002F`Do` for observability** — log, trace, or meter emissions without altering the stream. Chain `TapOnError` for error monitoring\n6. **Prefer `samber\u002Flo` for simple transforms** — if the data is a finite slice and you need Map\u002FFilter\u002FReduce, use `lo`. Reach for `ro` when data arrives over time, from multiple sources, or needs retry\u002Ftimeout\u002Fbackpressure\n\n## Plugin Ecosystem\n\n40+ plugins extend ro with domain-specific operators:\n\n| Category | Plugins | Import path prefix |\n| --- | --- | --- |\n| Encoding | JSON, CSV, Base64, Gob | `plugins\u002Fencoding\u002F...` |\n| Network | HTTP, I\u002FO, FSNotify | `plugins\u002Fhttp`, `plugins\u002Fio`, `plugins\u002Ffsnotify` |\n| Scheduling | Cron, ICS | `plugins\u002Fcron`, `plugins\u002Fics` |\n| Observability | Zap, Slog, Zerolog, Logrus, Sentry, Oops | `plugins\u002Fobservability\u002F...`, `plugins\u002Fsamber\u002Foops` |\n| Rate limiting | Native, Ulule | `plugins\u002Fratelimit\u002F...` |\n| Data | Bytes, Strings, Sort, Strconv, Regexp, Template | `plugins\u002Fbytes`, `plugins\u002Fstrings`, etc. |\n| System | Process, Signal | `plugins\u002Fproc`, `plugins\u002Fsignal` |\n\nFor the full plugin catalog with import paths and usage examples, see [Plugin Ecosystem](.\u002Freferences\u002Fplugin-ecosystem.md).\n\nFor real-world reactive patterns (retry+timeout, WebSocket fan-out, graceful shutdown, stream combination), see [Patterns](.\u002Freferences\u002Fpatterns.md).\n\nIf you encounter a bug or unexpected behavior in samber\u002Fro, open an issue at [github.com\u002Fsamber\u002Fro\u002Fissues](https:\u002F\u002Fgithub.com\u002Fsamber\u002Fro\u002Fissues).\n\n## Cross-References\n\n- → See `golang-samber-lo` skill for finite slice transforms (Map, Filter, Reduce, GroupBy) — use lo when data is already in a slice\n- → See `golang-samber-mo` skill for monadic types (Option, Result, Either) that compose with ro pipelines\n- → See `golang-samber-hot` skill for in-memory caching (also available as an ro plugin)\n- → See `golang-concurrency` skill for goroutine\u002Fchannel patterns when reactive streams are overkill\n- → See `golang-observability` skill for monitoring reactive pipelines in production\n",{"name":5,"paths":54,"license":15,"metadata":56,"description":7,"allowed-tools":66,"compatibility":67,"user-invocable":68},[55],"**\u002F*.go",{"author":57,"version":58,"openclaw":59},"samber","1.2.0",{"emoji":60,"install":61,"homepage":62,"requires":63,"skill-library-version":65},"?",[],"https:\u002F\u002Fgithub.com\u002Fsamber\u002Fcc-skills-golang",{"bins":64},[47],"0.3.0","Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent mcp__context7__resolve-library-id mcp__context7__query-docs AskUserQuestion Bash(godig:*) Bash(gopls:*) LSP mcp__gopls__*","Designed for Claude Code, Codex or similar harness, and for projects using Golang.",true,"main","c349be0704bffe54a7191d1412faf564b08983ca","skills\u002Fsamber-golang\u002Fgolang-samber-ro",0,"https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills","https:\u002F\u002Fgithub.com\u002Frockcookies","2026-11-12 14:42:52",{"source":8,"skillName":5,"commands":77,"prompt":87,"zipAvailable":68},[78,81,84],{"tool":79,"command":80},"npx","npx skills add rockcookies\u002Fskills --skill golang-samber-ro",{"tool":82,"command":83},"bunx","bunx skills add rockcookies\u002Fskills --skill golang-samber-ro",{"tool":85,"command":86},"pnpm","pnpm dlx skills add rockcookies\u002Fskills --skill golang-samber-ro","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fsamber-golang\u002Fgolang-samber-ro\u002FSKILL.md",[89,95,99,103,107,111,115],{"path":90,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":93,"sourceHtmlUrl":94},"evals\u002Fevals.json","REFERENCE","参考文档",17758,"https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fsamber-golang\u002Fgolang-samber-ro\u002Fevals\u002Fevals.json",{"path":96,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":97,"sourceHtmlUrl":98},"references\u002Foperators-guide.md",14184,"https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fsamber-golang\u002Fgolang-samber-ro\u002Freferences\u002Foperators-guide.md",{"path":100,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":101,"sourceHtmlUrl":102},"references\u002Fpatterns.md",7430,"https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fsamber-golang\u002Fgolang-samber-ro\u002Freferences\u002Fpatterns.md",{"path":104,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":105,"sourceHtmlUrl":106},"references\u002Fplugin-ecosystem.md",5974,"https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fsamber-golang\u002Fgolang-samber-ro\u002Freferences\u002Fplugin-ecosystem.md",{"path":108,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":109,"sourceHtmlUrl":110},"references\u002Fruntime-and-interpretation.md",13632,"https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fkdense-qiime2-amplicon\u002Freferences\u002Fruntime-and-interpretation.md",{"path":112,"resourceType":91,"resourceTypeDesc":92,"sizeBytes":113,"sourceHtmlUrl":114},"references\u002Fsubjects-guide.md",5836,"https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fsamber-golang\u002Fgolang-samber-ro\u002Freferences\u002Fsubjects-guide.md",{"path":116,"resourceType":117,"resourceTypeDesc":118,"sizeBytes":119,"sourceHtmlUrl":120},"scripts\u002Famplicon_workflow.py","SCRIPT","脚本",15621,"https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fkdense-qiime2-amplicon\u002Fscripts\u002Famplicon_workflow.py",[122,145,163,186,198,212],{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":49},"01M6WMNKD3Y4H9FGM8Q901F507","hierarchical-agents-md","层级 AGENTS.md \u002F README.md：init、update、audit、reorganize、trim。 初始化 Agent 指令、代码改动后同步文档、检查文档漂移、重组仓库文档层级、精简规则与 Skills。 Not for 写业务代码或生成文档站点。","https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fcustom\u002Fhierarchical-agents-md\u002FSKILL.md",[],[129,130,131,132,133,134,45,135,136,137,138,139,140,141,142,143,144],"hierarchical agents md","agents md","party","init","third-party","true","packages","change","maintenance","初始化","文档","audit","for","README","update","python",{"skillNo":146,"name":147,"nameZh":6,"description":148,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":149,"categories":150,"keywords":154,"publishedAt":49},"01M6CFS6BRTQPFZCDHQP97HYXR","vueuse-functions","Apply VueUse composables where appropriate to build concise, maintainable Vue.js \u002F Nuxt features.","https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fvueuse\u002Fvueuse-functions\u002FSKILL.md",[151],{"categoryNo":152,"categoryName":153,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",[155,156,157,158,159,160,161,162],"functions","vueuse functions","js","vue","https","nuxt","build","github",{"skillNo":164,"name":165,"nameZh":6,"description":166,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":167,"categories":168,"keywords":173,"publishedAt":49},"01M6CFS34MDQXZPAWQFE5D7VGT","vue-testing-best-practices","Use for Vue.js testing. Covers Vitest, Vue Test Utils, component testing, mocking, testing patterns, and Playwright for E2E testing.","https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fvuejs-ai\u002Fvue-testing-best-practices\u002FSKILL.md",[169,172],{"categoryNo":170,"categoryName":171,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":152,"categoryName":153,"taxonomyType":21,"taxonomyTypeDesc":22},[174,158,175,176,177,178,179,180,181,182,162,183,184,185,157],"best practices","testing best practices","testing","vue testing best practices","e2e testing","playwright","test","testing patterns","component","vitest","e2e","use",{"skillNo":187,"name":188,"nameZh":6,"description":189,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":190,"categories":191,"keywords":193,"publishedAt":49},"01M6CFS0N19MSJNTVM9AEQ7Z73","vue-router-best-practices","Vue Router 4 patterns, navigation guards, route params, and route-component lifecycle interactions.","https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fvuejs-ai\u002Fvue-router-best-practices\u002FSKILL.md",[192],{"categoryNo":152,"categoryName":153,"taxonomyType":21,"taxonomyTypeDesc":22},[194,174,158,195,162,182,196,197],"vue router best practices","router","navigation","lifecycle",{"skillNo":199,"name":200,"nameZh":6,"description":201,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":202,"categories":203,"keywords":205,"publishedAt":49},"01M6CFRYN31RFQFTE41Z6DCGKE","vue-pinia-best-practices","Pinia stores, state management patterns, store setup, and reactivity with stores.","https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fvuejs-ai\u002Fvue-pinia-best-practices\u002FSKILL.md",[204],{"categoryNo":152,"categoryName":153,"taxonomyType":21,"taxonomyTypeDesc":22},[174,158,206,207,208,209,162,210,211],"vue pinia best practices","pinia","state","state management","management","setup",{"skillNo":213,"name":214,"nameZh":6,"description":215,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":216,"categories":217,"keywords":223,"publishedAt":49},"01M6CFRW2DKXJHP05DYJ3P3Y2S","vue-options-api-best-practices","Vue 3 Options API style (data(), methods, this context). Each reference shows Options API solution only.","https:\u002F\u002Fgithub.com\u002Frockcookies\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fvuejs-ai\u002Fvue-options-api-best-practices\u002FSKILL.md",[218,219,222],{"categoryNo":152,"categoryName":153,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":220,"categoryName":221,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},[158,174,224,225,226,41,227,162,228,34],"vue options api best practices","api","only","reference","methods"]