golangで名前だけ知っていて、試していない機能がいくつもある。
今回はgoroutineをいくつか動かしてみる。
まず、取りあえず動かないこともないコードからいこう。
01: package main 02: 03: import ( 04: "fmt" 05: "time" 06: ) 07: 08: func gor1() { 09: fmt.Printf("gor1\n") 10: } 11: 12: func main() { 13: go gor1() 14: time.Sleep(time.Second) 15: }
1秒もあればgoroutineの1つくらいは動くよね、というだけで、環境によってはfmt.Printf()が出力されなくてもおかしくはない。
関係ないけど、golangは前方参照だっけ?
> There are no forward declarations and no header files; everything is declared exactly once.
https://golang.org/doc/faq#principles
違うそうだ。
まあ、前方参照のつもりで書いていても問題ないだろう。
chanを使うと、その変数は通信チャネルになるらしい。
01: package main 02: 03: import ( 04: "fmt" 05: ) 06: 07: func gor1(channel chan int) { 08: fmt.Printf("gor1\n") 09: channel <- 0 10: } 11: 12: func main() { 13: cn := make(chan int) 14: go gor1(cn) 15: <-cn 16: }
なんかもったいない使い方だが、まあ、普通ならgoroutineにしなくてよい関数をそうしているからだろう。
01: package main 02: 03: import ( 04: "fmt" 05: "time" 06: ) 07: 08: func gor1(channel1 chan int, channel2 chan int) { 09: fmt.Printf("gor1-1\n") 10: channel1 <- 0 11: time.Sleep(time.Second * 3) 12: fmt.Printf("gor1-2\n") 13: channel2 <- 0 14: } 15: 16: func main() { 17: cn1 := make(chan int) 18: cn2 := make(chan int) 19: go gor1(cn1, cn2) 20: <-cn1 21: <-cn2 22: }
ふむ、複数chanでもいいのか。
あ、chanの待つ順番をcn2を先にするとどうなるだろう?
$ go run .
gor1-1
fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan receive]:
main.main()
/home/xxx/golang/test/src/ex2/ex2.go:20 +0xa5goroutine 18 [chan send]:
main.gor1(0xc000062060, 0xc0000620c0)
/home/xxx/golang/test/src/ex2/ex2.go:10 +0x7d
created by main.main
/home/xxx/golang/test/src/ex2/ex2.go:19 +0x8e
exit status 2
デッドロックするんだ。
cn1は後でチェックすればいいだけかと思ったが、そういう問題でも無いのか?
Go言語—バッファなしのチャンネルに送受信するとデッドロックが起こる理由 - Qiita
https://qiita.com/YumaInaura/items/943c24ffb64df5e01c65
ほう、cn1がまだ受信の待ち受け状態じゃないのに送りつけたからダメ、ということか。
なので、cn2を1つだけバッファを持たせれば動く。
01: package main 02: 03: import ( 04: "fmt" 05: "time" 06: ) 07: 08: func gor1(channel1 chan int, channel2 chan int) { 09: fmt.Printf("gor1-1\n") 10: channel1 <- 0 11: time.Sleep(time.Second * 3) 12: fmt.Printf("gor1-2\n") 13: channel2 <- 0 14: } 15: 16: func main() { 17: cn1 := make(chan int, 1) 18: cn2 := make(chan int) 19: go gor1(cn1, cn2) 20: <-cn2 21: <-cn1 22: }
chanは双方向のようだ。
01: package main 02: 03: import ( 04: "fmt" 05: "time" 06: ) 07: 08: func gor1(channel1 chan int, channel2 chan int) { 09: fmt.Printf("gor1-1: %d\n", <-channel1) 10: time.Sleep(time.Second * 3) 11: fmt.Printf("gor1-2\n") 12: channel2 <- 2 13: } 14: 15: func main() { 16: cn1 := make(chan int) 17: cn2 := make(chan int) 18: go gor1(cn1, cn2) 19: fmt.Printf("main-1\n") 20: cn1 <- 1 21: fmt.Printf("main-2: %d\n", <-cn2) 22: }
同時に両方書き込むようなタイミングがあるようだったら、mutexみたいな排他処理をするのだろうか。
いろいろ種類がありそうなので、また今度調べよう。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。