##channelとは?
Goroutineは並行実行されているので、通常だとデータのやりとりができません。
しかし、channelというのををつかうとデータのやりとりができます。
トンネルをつなぐようなイメージです!
package main
import (
"fmt"
)
func goroutine1(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
//チャネルにデータを送信
c <- sum
}
func main() {
s := []int{1, 2, 3, 4}
c := make(chan int)
go goroutine1(s, c)
//送られてきたデータを受信
p := <-c
fmt.Println(p) // => 10
}
c <- sum でcに値を送信し、p := <-c で受信しています。ここでは受信するまでブロッキングされていて、pはsumを受信するまで待っている状態です。sync.Waitと同じような状態ですね!
##Buffered channels
バッファとはプログラムで処理を行なうときに、データを一時的に格納するためのメモリー領域のことをいいます。
チャネルに一時データを保存するイメージです。
package main
import "fmt"
func main() {
//2つまでバッファを保存できる
ch := make(chan int, 2)
ch <- 100
//len()でチャネルの長さを調べられる
fmt.Println(len(ch))
ch <- 200
fmt.Println(len(ch))
//3つめのデータを送信しようとするとエラーになる
ch <- 300
fmt.Println(len(ch)) // => fatal error: all goroutines are asleep - deadlock!
}
実行結果
1
2
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/tmp/sandbox795806942/prog.go:11 +0x16f
2つまでしか保存できないので、3つめを送信しようとすると当然ですがエラーになります。(デッドロック)
↓にように手前で一個チャネルを取りだしてから300を送信すれば、エラーにならなくなります。
func main() {
ch := make(chan int, 2)
ch <- 100
fmt.Println(len(ch))
ch <- 200
fmt.Println(len(ch))
x := <-ch
fmt.Println(x)
ch <- 300
fmt.Println(len(ch))
}
実行結果
1
2
100
2
次に以下のコードをご覧ください↓
package main
import "fmt"
func main() {
ch := make(chan int, 2)
ch <- 100
fmt.Println(len(ch))
ch <- 200
fmt.Println(len(ch))
for c := range ch {
fmt.Println(c)
}
}
これはチャネルをrangeでループさせようとしているのですが、これはエラーになります。
実行結果
1
2
100
200
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/tmp/sandbox892357489/prog.go:12 +0x1f3
これは存在しない3つ目のチャネルまでループしようとしてしまうからです。
2つ目のチャネルでループ処理を止めるにはチャネルを一旦クローズする必要があります。
そのためにはclose(ch)を記述する必要があります。
package main
import "fmt"
func main() {
ch := make(chan int, 2)
ch <- 100
fmt.Println(len(ch))
ch <- 200
fmt.Println(len(ch))
close(ch)
for c := range ch {
fmt.Println(c)
}
}
実行結果
1
2
100
200
##最後まで読んでいただきありがとうございます!
ご指摘などございましたら、コメントいただけると幸いです!!