RxGoでリアクティブプログラミングに入門する

Go2 Advent Calendar 2018の19日目の記事です。

こんにちは@mrsekutです。

参加者が多すぎて、1から4まであるGoのAdvent Calendarの2つめってだけで、最近話題のGo言語バージョン2って意味ではないです(え、ちゃうよね??)

今回は、Go言語用のリアクティブプログラミングライブラリのRxGoの話をします。

 

リアクティブプログラミングとRxの概要

リアクティブプログラミングは、なんらかのイベント発生の通知を受け取って処理を実行するようなプログラムを組んでいくプログラミングのパラダイムです。

よく用いられる具体例にExcelがあります。
セルの中に計算式を書いておけば、それに依存するセルの数値を変更すると、瞬時にその答えが書き換わりますよね。

これは、裏側では依存するセルを監視し続けるコードを書くことになりますが、以下の記事でも解説されているように、従来の書き方だと幾分冗長になってしまいます。

そこにリアクティブプログラミングを使うことで、より簡潔に動作を管理することができるようになります。

リアクティブプログラミングについての詳細は以下の記事がわかりやすかったので、参考にしてみてください。

【参考】

そして、各言語でリアクティブプログラミングを実装するための便利ライブラリとにReactiveXというものがあります。
Java、JS、C#、Swiftと色々ある中に、Go言語もあり、それがRxGoです。

ReactiveXのサイトのトップページには以下のように書いてあります。

ReactiveX is a combination of the best ideas from the Observer pattern, the Iterator pattern, and functional programming.

ObserverパターンとIteratorパターンと関数型プログラミングの良いとこ取りのようです。

どうでもいいですが、たまたま(?)この3つそれぞれに関して備忘録を残してたので良かったら御覧ください。

【参考】

では、次にこの中からObsrverパターンのおさらいをさらっとします。

Observerパターンおさらい

Observerパターンは、あるオブジェクトの状態変化を他のオブジェクトへ通知するときに用いられるGoFデザインパターンの一つです。

Observerパターンは「監視する側(Observer)」と「監視される側(Subject)」に分かれます。

上で紹介した備忘録記事では、本屋さんの入荷通知システムの例を実装してみました。

「本屋さん」と、「欲しい本が入荷されたらすぐに購入したいと思っているAさん」が登場人物です。

Observerパターンに当てはめると、本屋さんが監視される側であるSubject、Aさんが監視する側のObserverになります。

「本屋さんに本が入荷した」というイベントを、監視しているAさんが即座に知ることができ、必要であればそれに対する何かのアクション(購入など)を実行できます。

Observerパターンはこんな感じですが、Rxでは少し用語が変わり、「Observer(監視する方)」と「Observable(監視される方)」になります。

とりあえずRxGoの最小のコードを動かしてみる

前振りが長くなりすぎましたが、やっとGoの話です。
詳細は一旦置いておいてコードを動かしてみます。

インストール

以下のコマンドでRxGoをインストールできます。

超シンプルなコード

超シンプルなコードを見てみましょう。

出力はこんな感じ。

11から20までの数字が出力されました。
for文を使わずにこんな処理が書けました。

では、RxGoの基本とともに上のコードで何をやったかを見ていきます。

RxGoのキホン3要素

Rxには大きく分けて以下の3つのキーワードがあります。

  • Observable
  • Observer
  • Subscription

ひとつずつ簡単に見ていきます。

Observableとは

まずは、observableです。
observableはその名の通り監視される側で、データの生成と、そのデータの通知します。

上記のコードの例では、Range()や、Skip()がこれにあたります。

Range(1, 21)で1から20までの数値のデータを生成し、次に流します。

Skip(10)では、最初の10個のデータを飛ばして、次に流します。

Observerとは

Observerは、逆に監視をする側で、データを受信し、その都度必要な処理を行います。
上のコードでは、onNextの部分が該当します。

Observableで作られたデータが流れてくるので、ここで処理をします。
今回の例では「Processing: n」というように文字列と数値を出力する処理を書きました。

簡単のため、今回のコードには載せませんでしたが、Observerには大きく分けて3つのメソッドがあります。

今回紹介した「次の処理をするonNext」と、「エラー時の処理であるonError」、「終了時に走らせる処理であるonDone」の3つです。
必要であれば、onErrorとonDoneも作ることで柔軟なプログラムを書けるようになります。

Subscriptionとは

これもその名の通り、購読するものです。

subscribe()を使って、ObservableにObserverを登録します。

RxGoまとめ

ドキュメントには、以下のように要約された一文がありました。

The pattern is that you Subscribe to an Observable using an Observer.

これをコードで表すなら以下のようになります。

少しだけ中を覗いてみる

RxGoで用意されているメソッドの内部を覗いてみると、各所でgoroutineが使われているのがわかります。

例えば上で出てきたobservable.Range()のコード

各メソッドが小さく、やっていること単純なので、Goの勉強として眺めていると得られることも多そうな気がします。

所感

今回はリアクティブプログラミングとRxGoについて書いてみました。

RxGoが他の言語のRxと異なるのは、Go特有の機能であるチャネルを使っている点でしょうか。

Subscribeメソッドが呼び出されたとき、複数のgoroutineが生成され、非同期処理をやってくれます。

リアクティブプログラミングができるようになると、プログラミングの仕方が変わり見える世界も広がりそうな気がします。

RxGo自体はまだ小さく、バージョン2も開発中のようです。

他の言語のrxなども触って何か作ってみたいです。

参考

RxJSのものですが、APIの使い方を知るのに参考にさせていただきました。

【参考】bouzuya’s RxJS Advent Calendar 2015 – Adventar