問題
以前 Go言語のchannelって一体何よ ~基礎編~【golang】 - DRYな備忘録 のエントリを書いて分かった気になってたgolangのchan
ですが、このたびそらで書いてみて動いたのでこれはちょっと理解できたと思っていいだろうということでメモるよ。
並行処理とは?
複数のマイクロプロセッサなどに処理を分散して割り当て、同時に計算・処理を行うことで、システム全体の処理性能を向上させる技術。また、そのような環境を効率的に活用するためのソフトウェアやプログラミングの手法の総称。
並列処理とは 〔 パラレルプロセッシング 〕 【 parallel processing 】 - 意味/解説/説明/定義 : IT用語辞典
メインの処理を止めることなく、別の場所で並行して処理をすることで、非同期で処理できたり、メインから複数の処理を同時にできたりする
Go言語の並行処理goroutine
Go言語では言語で並行処理へのアプローチを用意してくれていて、超簡単に並行処理が書ける。それがgoroutine
(「ゴルーチン」と呼んでる人がいてわさわさするんだけど、「ゴールーチン」でいいんだよね?)
以下、例
package main import "fmt" import "time" func myRoutine(mess string) { fmt.Printf( "ルーチンが%sを受け取ったお(^ω^ ≡ ^ω^)\n", mess, ) } func main() { // goステートメントに関数を渡すだけで // goroutineがつくられる go myRoutine("hoge") go myRoutine("fuga") // goroutineはmainが死ぬと死ぬので // とりあえずmainを延命するよ time.Sleep(1 * time.Second) fmt.Println("Main \(^o^)/") }
Try here! : Go Playground
並行処理あるある
- 並行して走る処理が複数あると、単一のリソースに対する競合が発生する
上記の例だと、リソースXがどういう値なのか保証できない困った
Go言語にはchannel
というのが用意されてる
上記の問題に対して、Go言語ではchannel
というものを用意している。
channel
は、(mainを含む)複数のgoroutineがお互いにメッセージングをするときに、共通の窓口、まさにチャネルとして動いてくれる。
package main import "fmt" import "time" func listen(sender chan string) { log := make([]string, 3) // 与えられたチャネルからの受信を待つルーチンを生成 // goステートメントに渡す関数は無名関数でも可 go func() { // これは無限ループの書き方 for { // 「受信を待つ」書式 mess := <-sender // ここで受信するまで // このルーチンの処理は止まっている // 受信し次第、以下が動き出す log = append(log, mess) fmt.Printf("Got message: %v (%v)\n", mess, log) } }()// 無名関数のこれ忘れがち! } func main() { // stringを送受信できるチャネル sender := make(chan string) // チャネルを渡してgoroutineを立てる listen(sender) // チャネルに流し込んだりする sender <- "foo" sender <- "bar" sender <- "buz" time.Sleep(1 * time.Second) fmt.Println("Main \(^o^)/") }
Try here! : Go Playground
参考になるサンプルとか
The Revel Web Framework for Goのサンプルの中にあるchat
とかが結構参考になった。
% go get github.com/revel/revel
% vi $GOPATH/src/github.com/revel/revel/samples/chat/
でソースを見たりできる。
たぶんよくある使い方としては
- グローバルなチャネルを宣言する
- 適当に非同期で処理したい内容を書いたルーチンを
go
して立てとく - ルーチンはグローバルなチャネルからの受信を待っている
- mainプロセスからグローバルなチャネルにメッセージを送る
- ルーチンが動く
みたいな感じだと思ふ。
雑感
これをまとめてる最中でもやっぱりまだ分からないことが多いので、引き続き触って書いて、勉強していきたい。
Go言語たのしい! ✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌
DRYな備忘録