Channel
Golangのspecificationの日本語訳と、ちょっとした遊びぐらいのコードを載せていく感じで進めようと思うので、
すでにGolangでコードを書いている人にはつまらないかもしれないです
また、間違っている部分があればぜひご指摘いただけると嬉しいです🙇♂️
想定する読者層
- Golang初めてそこまで期間が経っていない
- 英語の公式読むの辛い
Channel Types
本記事は公式のドキュメントを参考にしています
- https://golang.org/ref/spec#Channel_types
用途としては、goroutine同士の値のやりとりを行えるようにすることで並列処理を実装することです
Channelの宣言
Channelとは並列実行を可能にする機能を持った型です。Channelは受信と送信の2つの機能によって成り立ち、初期化されていない時の値はnilになります。
var c chan int
受信と送信のChannelの宣言
受信と送信を分けるには <-
を使い、以下のようにします
chan<- type はtype型の受信用のchannelを作り
<-chan type はtype型の送信用のchannelを作ります
var rc chan<- int // 受信用
var sc <-chan int // 送信用
一般的な宣言方法?
私自身は以下のようなchannelの宣言をしたことがなく、後述するmake関数を使った初期化をよく使うため、このような宣言方法もあるよという程度にしておきます(varを使った宣言をすることのメリットが分かれば追記しますね)
var ch chan<- chan int
var ch_1 chan<- <-chan int
var ch_2 <-chan <-chan int
var ch_3 chan (<-chan int)
Channelの初期化
Channelの初期化はgolangのbuilt-in関数であるmakeを使用します
typeは型、sizeはint型でchannelの容量を指定します。
make(chan type, size)
sizeを指定しないで初期化した場合は0で初期化されます
c := make(chan int, 10) // len=0, cap=10
ch := make(chan int) // len=0, cap=0
nil Channelは通信の準備ができていないので注意です(varで宣言した時などがそれにあたります)
サンプルプログラム
goroutineと、channelの送受信のサンプルプログラムです。
一つのgoroutine
package main
import (
"fmt"
)
func main() {
c := make(chan int, 1)
go receive(c)
result := <-c
close(c)
fmt.Println(result) // 10
}
func receive(ch chan<- int) {
ch <- 10
}
複数のgoroutineを使用した場合
package main
import (
"fmt"
)
func main() {
c := make(chan int, 1)
go receive(c)
go receive(c)
fmt.Println(<-c)
fmt.Println(<-c)
close(c)
}
func receive(ch chan<- int) {
ch <- 10
}
エラーが発生する場合
make(chan type, size) にて初期化した時のsizeを超える受信があった場合にはエラーが発生します
package main
import (
"fmt"
)
func main() {
c := make(chan int, 1)
go receive(c)
go receive(c)
fmt.Println(<-c)
fmt.Println(<-c)
fmt.Println(<-c) // error
close(c)
}
func receive(ch chan<- int) {
ch <- 10
}
参考になりそうなプログラムを思いついたら追記していきます