{"id":36849887,"url":"https://github.com/reactivego/rx","last_synced_at":"2026-01-12T14:36:36.487Z","repository":{"id":57522155,"uuid":"106057607","full_name":"reactivego/rx","owner":"reactivego","description":"Reactive Extension for Go","archived":false,"fork":false,"pushed_at":"2025-05-31T13:41:32.000Z","size":2132,"stargazers_count":17,"open_issues_count":4,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-01T01:47:53.708Z","etag":null,"topics":["generics","observable","observable-streams","reactive-extension","reactive-extensions","reactive-programming","reactivex","rx","rxgo"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reactivego.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-10-06T23:10:44.000Z","updated_at":"2025-05-31T13:41:16.000Z","dependencies_parsed_at":"2025-03-21T22:22:13.988Z","dependency_job_id":"2c4e50ed-3b9e-4f2e-96cd-3547fc1da509","html_url":"https://github.com/reactivego/rx","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/reactivego/rx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactivego%2Frx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactivego%2Frx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactivego%2Frx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactivego%2Frx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reactivego","download_url":"https://codeload.github.com/reactivego/rx/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactivego%2Frx/sbom","scorecard":{"id":765915,"data":{"date":"2025-08-11","repo":{"name":"github.com/reactivego/rx","commit":"e4062b25593b76ce3d74cf81afc5a7009de5377c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.3,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"15 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T00:47:16.003Z","repository_id":57522155,"created_at":"2025-08-23T00:47:16.003Z","updated_at":"2025-08-23T00:47:16.003Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28340403,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T12:22:26.515Z","status":"ssl_error","status_checked_at":"2026-01-12T12:22:10.856Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["generics","observable","observable-streams","reactive-extension","reactive-extensions","reactive-programming","reactivex","rx","rxgo"],"created_at":"2026-01-12T14:36:36.392Z","updated_at":"2026-01-12T14:36:36.473Z","avatar_url":"https://github.com/reactivego.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rx\n\n    import \"github.com/reactivego/rx\"\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/reactivego/rx.svg)](https://pkg.go.dev/github.com/reactivego/rx)\n\nPackage `rx` provides _**R**eactive E**x**tensions_, a powerful API for asynchronous programming in Go, built around [observables](#observables) and [operators](#operators) to process streams of data seamlessly.\n\n## Prerequisites\n\nYou’ll need [*Go 1.23*](https://golang.org/dl/) or later, as the implementation depends on language support for generics and iterators.\n\n## Observables\n\nIn `rx`, an [**Observables**](http://reactivex.io/documentation/observable.html) represents a stream of data that can emit items over time, while an **Observer** subscribes to it to receive and react to those emissions. This reactive approach enables asynchronous and concurrent operations without blocking execution. Instead of waiting for values to become available, an observer passively listens and responds whenever the observable emits data, errors, or a completion signal.\n\nThis page introduces the **reactive pattern**, explaining what **Observables** and **Observers** are and how subscriptions work. Other sections explore the powerful set of [**Operators**](https://reactivex.io/documentation/operators.html) that allow you to transform, combine, and control data streams efficiently.\n\nAn Observable:\n\n- is a stream of events.\n- assumes zero to many values over time.\n- pushes values\n- can take any amount of time to complete (or may never)\n- is cancellable\n- is lazy (it doesn't do anything until you subscribe).\n\nExample\n```go\npackage main\n\nimport \"github.com/reactivego/x\"\n\nfunc main() {\n    x.From[any](1,\"hi\",2.3).Println().Wait()\n}\n```\n\u003e Note the program creates a mixed type `any` observable from an int, string and a float64.\n\nOutput\n```\n1\nhi\n2.3\n```\nExample\n```go\npackage main\n\nimport \"github.com/reactivego/rx\"\n\nfunc main() {\n    rx.From(1,2,3).Println().Wait()\n}\n```\n\u003e Note the program uses inferred type `int` for the observable.\n\nOutput\n```\n1\n2\n3\n```\n\nObservables in `rx` offer several advantages over standard Go channels:\n\n### Hot vs Cold Observables\n\n- **Hot Observables** emit values regardless of subscription status. Like a live broadcast, any values emitted when no subscribers are listening are permanently missed. Examples include system events, mouse movements, or real-time data feeds.\n\n- **Cold Observables** begin emission only when subscribed to, ensuring subscribers receive the complete data sequence from the beginning. Examples include file contents, database queries, or HTTP requests that are executed on-demand.\n\n### Rich Lifecycle Management\n\nObservables offer comprehensive lifecycle handling. They can complete normally, terminate with errors, or continue indefinitely. Subscriptions provide fine-grained control, allowing subscribers to cancel at any point, preventing resource leaks and unwanted processing.\n\n### Time-Varying Data Model\n\nUnlike traditional variables that represent static values, Observables elegantly model how values evolve over time. They represent the entire progression of a value's state changes, not just its current state, making them ideal for reactive programming paradigms.\n\n### Native Concurrency Support\n\nConcurrency is built into the Observable paradigm. Each Observable conceptually operates as an independent process that asynchronously pushes values to subscribers. This approach naturally aligns with concurrent programming models while abstracting away much of the complexity typically associated with managing concurrent operations.\n\n## Operators\n\nOperators form a language for expressing programs with Observables. They transform, filter, and combine one or more Observables into new Observables, allowing for powerful data stream processing. Each operator performs a specific function in the reactive pipeline, enabling you to compose complex asynchronous workflows through method chaining.\n\n### Index\n\n[__All__](https://pkg.go.dev/github.com/reactivego/rx#Observable.All) converts an Observable stream into a Go 1.22+ iterator sequence that provides each emitted value paired with its sequential zero-based index\n\n[__All2__](https://pkg.go.dev/github.com/reactivego/rx#All2)\nconverts an Observable of Tuple2 pairs into a Go 1.22+ iterator sequence that yields each tuple's components (First, Second) as separate values.\n\n[__Append__](https://pkg.go.dev/github.com/reactivego/rx#Append)\ncreates a pipe that appends emitted values to a provided slice while forwarding them to the next observer, with a method variant available for chaining.\n\n[__AsObservable__](https://pkg.go.dev/github.com/reactivego/rx#AsObservable)\nprovides type conversion between observables, allowing you to safely cast an Observable of one type to another, and to convert a typed Observable to an Observable of 'any' type (and vice versa).\n\n[__AsObserver__](https://pkg.go.dev/github.com/reactivego/rx#AsObserver) converts an Observer of type `any` to an Observer of a specific type T.\n\n[__Assign__](https://pkg.go.dev/github.com/reactivego/rx#Observable.Assign) stores each emitted value from an Observable into a provided pointer variable while passing all emissions through to the next observer, enabling value capture during stream processing.\n\n[__AutoConnect__](https://pkg.go.dev/github.com/reactivego/rx#Connectable.AutoConnect) makes a (Connectable) Multicaster behave like an ordinary Observable that automatically connects the mullticaster to its source when the specified number of observers have subscribed to it.\n\n[__AutoUnsubscribe__](https://pkg.go.dev/github.com/reactivego/rx#Observable.AutoUnsubscribe)\n\n[__BufferCount__](https://pkg.go.dev/github.com/reactivego/rx#BufferCount)\n\n[__Catch__](https://pkg.go.dev/github.com/reactivego/rx#Observable.Catch) recovers from an error notification by continuing the sequence without emitting the error but switching to the catch ObservableInt to provide items.\n\n[__CatchError__](https://pkg.go.dev/github.com/reactivego/rx#Observable.CatchError)  catches errors on the Observable to be handled by returning a new Observable or throwing error.\n\n__CombineAll__\n\n__CombineLatest__ combines multiple Observables into one by emitting an array containing the latest values from each source whenever any input Observable emits a value, with variants (__CombineLatest2__, __CombineLatest3__, __CombineLatest4__, __CombineLatest5__) that return strongly-typed tuples for 2-5 input Observables respectively.\n\n__Concat__ combines multiple Observables sequentially by emitting all values from the first Observable before proceeding to the next one, ensuring emissions never overlap.\n\n__ConcatAll__ transforms a higher-order Observable (an Observable that emits other Observables) into a first-order Observable by subscribing to each inner Observable only after the previous one completes.\n\n__ConcatMap__ projects each source value to an Observable, subscribes to it, and emits its values, waiting for each one to complete before processing the next source value.\n\n__ConcatWith__ extends an Observable by appending additional Observables, ensuring that emissions from each Observable only begin after the previous one completes.\n\n__Connectable__ is an Observable with delayed connection to its source, combining both Observable and Connector interfaces. It separates the subscription process into two parts: observers can register via Subscribe, but the Observable won't subscribe to its source until Connect is explicitly called. This enables multiple observers to subscribe before any emissions begin (multicast behavior), allowing a single source Observable to be efficiently shared among multiple consumers. Besides inheriting all methods from Observable and Connector, Connectable provides the convenience methods __AutoConnect__ and __RefCount__ to manage connection behavior.\n\n__Connect__ establishes a connection to the source Observable and returns a Subscription that can be used to cancel the connection when no longer needed.\n\n__Connector__ provides a mechanism for controlling when a Connectable Observable subscribes to its source, allowing you to connect the Observable independently from when observers subscribe to it. This separation enables multiple subscribers to prepare their subscriptions before the source begins emitting items. It has a single method __Connect__.\n\n__Constraints__ type constraints __Signed__, __Unsigned__, __Integer__ and __Float__ copied verbatim from `golang.org/x/exp` so we could drop the dependency on that package.\n\n__Count__ returns an Observable that emits a single value representing the total number of items emitted by the source Observable before it completes.\n\n__Create__ constructs a new Observable from a Creator function, providing a bridge between imperative code and the reactive Observable pattern. The Observable will continue producing values until the Creator signals completion, the Observer unsubscribes, or the Creator returns an error.\n\n__Creator__ is a function type that generates values for an Observable stream. It receives a zero-based index for the current iteration and returns a tuple containing the next value to emit, any error that occurred, and a boolean flag indicating whether the sequence is complete.\n\n__Defer__\n\n__Delay__\n\n__DistinctUntilChanged__ only emits when the current value is different from the last.\n\n__Do__ calls a function for each next value passing through the observable.\n\n__ElementAt__ emit only item n emitted by an Observable.\n\n__Empty__ creates an Observable that emits no items but terminates normally.\n\n__EndWith__\n\n__Equal__\n\n__Err__\n\n__ExhaustAll__\n\n__ExhaustMap__\n\n__Filter__ emits only those items from an observable that pass a predicate test.\n\n__First__ emits only the first item from an Observable.\n\n__Fprint__\n\n__Fprintf__\n\n__Fprintln__\n\n__From__ creates an observable from multiple values passed in.\n\n__Go__ subscribes to the observable and starts execution on a separate goroutine, ignoring all emissions from the observable sequence. This makes it useful when you only care about side effects and not the actual values. Returns a Subscription that can be used to cancel the subscription when no longer needed.\n\n__Ignore[T]__ creates an Observer[T] that simply discards any emissions from an Observable. It is useful when you need to create an Observer but don't care about its values.\n\n__Interval__ creates an ObservableInt that emits a sequence of integers spaced by a particular time\nterval.\n\n__Last__ emits only the last item emitted by an Observable.\n\n__Map__ transforms the items emitted by an Observable by applying a function to each item.\n\n__MapE__\n\n__Marshal__\n\n__MaxBufferSizeOption__, __WithMaxBufferSize__\n\n__Merge__ combines multiple Observables into one by merging their emissions.\n\n__MergeAll__ flattens a higher order observable by merging the observables it emits.\n\n__MergeMap__ transforms the items emitted by an Observable by applying a function to each item an\nturning an Observable.\n\n__MergeWith__ combines multiple Observables into one by merging their emissions.\n\n__Multicast__\n\n__Must__\n\n__Never__ creates an Observable that emits no items and does't terminate.\n\n__Observable__\n\n__Observer__\n\n__Of__ emits a variable amount of values in a sequence and then emits a complete notification.\n\n__OnComplete__\n\n__OnDone__\n\n__OnError__\n\n__OnNext__\n\n__Passthrough__ just passes through all output from the Observable.\n\n__Pipe__\n\n__Print__\n\n__Printf__\n\n__Println__ subscribes to the Observable and prints every item to os.Stdout.\n\n__Publish__ returns a multicasting Observable[T] for an underlying Observable[T] as a Connectable[T] type.\n\n__Pull__\n\n__Pull2__\n\n__Race__\n\n__RaceWith__\n\n__Recv__\n\n__Reduce__ applies a reducer function to each item emitted by an Observable and the previous reducer\nsult.\n\n__ReduceE__\n\n__RefCount__ makes a Connectable behave like an ordinary Observable.\n\n__Repeat__ creates an observable that emits a sequence of items repeatedly.\n\n__Retry__ if a source Observable sends an error notification, resubscribe to it in the hopes that it\nll complete without error.\n\n__RetryTime__\n\n__SampleTime__ emits the most recent item emitted by an Observable within periodic time intervals.\n\n__Scan__ applies a accumulator function to each item emitted by an Observable and the previous\ncumulator result.\n\n__ScanE__\n\n__Scheduler__\n\n__Send__\n\n__Share__\n\n__Skip__ suppresses the first n items emitted by an Observable.\n\n__Slice__\n\n__StartWith__ returns an observable that, at the moment of subscription, will synchronously emit all values provided to this operator, then subscribe to the source and mirror all of its emissions to subscribers.\n\n__Subject__ is a combination of an observer and observable.\n\n__Subscribe__ operates upon the emissions and notifications from an Observable.\n\n__SubscribeOn__ specifies the scheduler an Observable should use when it is subscribed to.\n\n__Subscriber__\n\n__Subscription__\n\n__SwitchAll__\n\n__SwitchMap__\n\n__Take__ emits only the first n items emitted by an Observable.\n\n__TakeWhile__ mirrors items emitted by an Observable until a specified condition becomes false.\n\n__Tap__\n\n__Throw__ creates an observable that emits no items and terminates with an error.\n\n__Ticker__ creates an ObservableTime that emits a sequence of timestamps after an initialDelay has passed.\n\n__Timer__ creates an Observable that emits a sequence of integers (starting at zero) after an initialDelay has passed.\n\n__Tuple__\n\n__Values__\n\n__Wait__ subscribes to the Observable and waits for completion or error.\n\n__WithLatestFrom__ will subscribe to all Observables and wait for all of them to emit before emitting the first slice.\n\n__WithLatestFromAll__ flattens a higher order observable.\n\n__Zip__\n\n__ZipAll__\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactivego%2Frx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freactivego%2Frx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactivego%2Frx/lists"}