[Go言語 入門] Channel
golangで作ってみたいものがあり、golangを学び始めたので学習したことを書いていくノート。
---------------------------------------------------
サイトマップはこちら
---------------------------------------------------
第18回 Channel
前回 Goroutin の基本を学習した。
Goroutine では return文で値を返却できないのだが、値を返却したい場合はどのようにすればいいのか。
「channel」を使おう!
以下は、Goroutineを使った配列 s の値を合計して返すプログラムである。
// main.go
func sum(s []int, ch chan int) {
sum := 0
for _, v := range s {
sum += v
}
ch <- sum
}
func main() {
s := []int{10, 20, 30, 40, 50}
ch := make(chan int)
go sum(s, ch)
x := <-ch
fmt.Println(x)
}
// 実行結果
// 150
channel の宣言方法は以下
「変数名 := make(chan 型名)」
上記プログラムでは「ch := make(chan int)」で
int型データを受信するchannel を宣言している。
処理の流れは以下
1:Goroutine の sum関数に、配列sとchannel ch を渡す。
2:変数sumに合計値を格納
3:sumの値をchannelのchへ送信
4:変数xは、受信した ch(sum)を初期値として設定
5:合計値を出力
※値を channel に渡すときは向きに注意
「channel名 <- 変数」と書くこと!
※受信した channel を変数へ格納する場合は channel 名のみでなく
「<- channel名」のように書くこと!
「<-」を忘れないように!
※channel が受信するまで次の処理が実行されない。
「sync.WaitGroup」で待つ必要がない!
~ Buffered Channels ~
channel には受信できるデータ数のキャパシティを設定することも可能。
キャパシティを設定する場合は以下のように記述する。
「変数名 := make(chan 型名 , キャパ数)」
// main2.go
func main() {
// Buffered Channels
ch := make(chan int, 3)
ch <- 100
ch <- 200
ch <- 300
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
}
// 実行結果
// 100
// 200
// 300
以下のようにキャパシティを超えた場合はエラーとなる。
func main() {
// Buffered Channels
ch := make(chan int, 2) // キャパ「2」とした
ch <- 100
ch <- 200
ch <- 300 // キャパオーバーでエラー
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
}
この場合は一度、受信したデータを吐き出してあげるとエラーとならずに次の channel を受信できる。
func main() {
// Buffered Channels
ch := make(chan int, 2)
ch <- 100
ch <- 200
fmt.Println(<-ch) // 一度吐き出して空きを作る
ch <- 300
fmt.Println(<-ch)
fmt.Println(<-ch)
}
// 実行結果
// 100
// 200
// 300
~ 受信した channel をfor文を使って取り出す方法 ~
for文で取り出す場合、channel をクローズする必要がある。
※クローズしないと以下の場合、4つ目の受信データを取りに行こうとしエラーとなる。
// for文でまとめて受信する方法
ch := make(chan string, 3)
ch <- "apple"
ch <- "orange"
ch <- "peach"
close(ch) // chクローズ
for v := range ch {
fmt.Println(v)
}
// 実行結果
// apple
// orange
// peach
以上