Reaktive Programmierung in Go (Golang) mit der Bibliothek RxGo
\n\nReaktive Programmierung ist ein Paradigma, das auf asynchrone Datenströme und die Verbreitung von Änderungen ausgerichtet ist. Im Go-Ökosystem (Golang) ist eine der leistungsstärksten Implementierungen dieses Paradigmas die Bibliothek RxGo (Reactive Extensions for Go). Sie ermöglicht es Entwicklern, mit Ereignissequenzen in einem deklarativen Stil zu arbeiten, was besonders nützlich bei der Verarbeitung von Benutzereingaben, Netzwerkanfragen, Nachrichten aus Kanälen und allen anderen asynchronen Datenquellen ist.
\n\nWas ist RxGo?
\nRxGo ist ein Port der beliebten Bibliothek ReactiveX (Reactive Extensions) auf die Sprache Go. Die Grundidee besteht darin, ein Observable (beobachtbarer Strom) zu erstellen, das Elemente aussendet, und einen Observer (Beobachter), der diesen Strom abonniert und auf eingehende Daten, Fehler oder den Abschluss des Stroms reagiert.
\nDie Bibliothek bietet eine umfangreiche Sammlung von Operatoren zur Transformation, Filterung, Kombination und Steuerung von Strömen. Der Hauptvorteil ist, dass der Code prägnant, lesbar und leicht testbar wird, insbesondere in komplexen Szenarien mit mehreren Ereignisquellen.
\n\nInstallation von RxGo
\nUm zu beginnen, installieren Sie das Paket mit go get:
go get -u github.com/reactivex/rxgo/v2\nStellen Sie sicher, dass Sie Version v2 verwenden, da sie die aktuelle API und Unterstützung für Go-Kontexte enthält.
\n\nGrundlegende Konzepte und Beispiele
\n\n1. Erstellen eines Observable
\nDer einfachste Weg, einen Strom zu erstellen, ist die Verwendung von rxgo.Just oder rxgo.FromChannel. Betrachten wir ein Beispiel mit Just:
package main\n\nimport (\n "context"\n "fmt"\n "github.com/reactivex/rxgo/v2"\n)\n\nfunc main() {\n observable := rxgo.Just(1, 2, 3, 4, 5)()\n ch := observable.Observe()\n for item := range ch {\n if item.Error() {\n fmt.Println("Fehler:", item.Err)\n } else {\n fmt.Println("Erhalten:", item.V)\n }\n }\n}\nDieser Code erstellt einen Strom aus fünf Zahlen. Die Methode Observe() gibt einen Kanal zurück, über den die Elemente eintreffen. Wichtig: In RxGo wird Backpressure (Gegendruck) verwendet – wenn der Verbraucher langsam ist, werden die Daten gepuffert.
2. Transformationsoperatoren
\nOperatoren sind das Herz der reaktiven Programmierung. Beispielsweise transformiert Map jedes Element:
package main\n\nimport (\n "context"\n "fmt"\n "github.com/reactivex/rxgo/v2"\n)\n\nfunc main() {\n observable := rxgo.Just(1, 2, 3)().\n Map(func(ctx context.Context, i interface{}) (interface{}, error) {\n num := i.(int)\n return num * 10, nil\n }, rxgo.WithPool(2)) // parallele Verarbeitung\n\n for item := range observable.Observe() {\n fmt.Println(item.V)\n }\n}\nAusgabe: 10, 20, 30. Der Operator Map wendet eine Funktion auf jedes Element an. Der Parameter rxgo.WithPool(2) aktiviert die parallele Verarbeitung mit zwei Goroutinen.
3. Filtern und Zusammenführen von Strömen
\nMit Filter können unerwünschte Elemente herausgefiltert werden, und Merge führt mehrere Ströme zusammen:
package main\n\nimport (\n "fmt"\n "github.com/reactivex/rxgo/v2"\n)\n\nfunc main() {\n // Filtern von geraden Zahlen\n even := rxgo.Just(1, 2, 3, 4, 5)().\n Filter(func(i interface{}) bool {\n return i.(int)%2 == 0\n })\n\n // Zweiter Strom\n odd := rxgo.Just(10, 20, 30)()\n\n // Zusammenführen\n merged := rxgo.Merge(even, odd)\n\n for item := range merged.Observe() {\n fmt.Println(item.V) // 2, 4, 10, 20, 30\n }\n}\n\n4. Arbeiten mit Kanälen und Kontexten
\nRxGo lässt sich hervorragend in native Go-Kanäle integrieren. Erstellen wir ein Observable aus einem Kanal und fügen hinzu
Auch in der Bibliothek
Stripe für JavaScript (Node.js): Komplettes Tutorial mit Beispielen
gRPC für JavaScript (Node.js): Bibliotheken, Einrichtung und Codebeispiele
Vavr Java: Vollständige Anleitung mit Code-Beispielen