前の投稿では、Crystalをやってみる
http://qiita.com/tabetomo/items/754308a6cd48bcf56585
ch1 = Channel(String).new(1)
ch2 = Channel(String).new(1)
done = Channel(Bool).new()
spawn do
puts ch1.receive
puts ch2.receive
puts ch1.receive
done.send(true) # end
end
spawn do
ch1.send("apple")
ch2.send("orange")
end
ch1.send("grape")
done.receive
と言って、Crystal上でspawnで送受信する例をやってみました。このページでは同じことをgolangでやってみます。
注意、上記は、前投稿のコメント欄でいただいた修正版コードを利用させていただきました 。>karupanerura様ありがとうございます!。
(cristalではメッセージのバッファのサイズを指定できる。というので使っている)
elixirでのspawn + send/receive例
同じことをgolangでやる予定でしたが、先にelixirでやってみることにしました。elixirでは、こんな感じ。
defmodule Contest do
# 関数を使っていないのでモジュールは空
end
pid1 = spawn fn ->
receive do
{sender, msg} -> IO.puts(msg)
end
receive do
{sender, msg} -> IO.puts(msg)
end
receive do
{sender, msg} -> IO.puts(msg)
send(sender, "done")
end
end
send(pid1, {self, "apple"})
send(pid1, {self, "orange"})
send(pid1, {self, "grape"})
pid2 = spawn fn ->
send(pid1, {self, "apple"})
send(pid1, {self, "orange"})
receive do
msg -> IO.puts("pid2, " <> msg)
after
1_000 -> IO.puts("time out in pid2")
end
end
send(pid1, {self, "grape"})
receive do
msg -> IO.puts("parent, " <> msg)
after
1_000 -> IO.puts("time out in parent")
end
(解説)pid1へのsendでは、{self, "contents"}のタプルにして、自分のpid=selfを送っています。このpidは返信に使われます。pid1では、3通うけとると、sender宛に"done"を送ることにしています。pid2は、基本pid1にメッセージを送るだけですが、ここでも{self, "contents"}として返信先を書いています。3通受信後、pid1からの返信"done"が、pid2に届くのかparentに届くのか未定なので、ここではどちらでもメッセージを受け取るようにしています。pid2かparentかどちらか一方受け取れないので(受け取れない方がいつまでも待たないように)受信にタイムアウトを入れています。
実行例は、以下の通り
$ bash-3.2$ iex -S mix
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4]
[hipe] [kernel-poll:false] [dtrace]
Compiling 1 file (.ex)
grape
apple
orange
pid2, done
time out in parent
Interactive Elixir (1.3.2) - press Ctrl+C to exit (typ
)
iex(1)>
elixirでは1つのspawnで1つのチャネル(のはず)ということで、cystalの例のように1つのspawnで2つのチェネル(ch1, ch2)を受信!とはいかなかったですが、なんとか近いものは動作させることができました。Elixlirでは100万個のspawnを作ってもすぐ終了する(高速!)。らしいので、ぜひ今度は是非やってみたいですね。
Ctrl`で、terminalが立ちあがって作業できるので、vscodeは便利。