channel
package main
import "fmt"
// SlieceとChannelを扱う関数
func gorooutine1(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
// <- Channelに送信
c <- sum
}
func main() {
s := []int{1, 2, 3, 4, 5}
// channel integerを扱う
c := make(chan int)
go gorooutine1(s, c)
// <- c でChannelから受け取るまで待機
x := <-c
fmt.Println(x)
}
15
キューのような使い方
- 2つのチャンネルを並列実行しても2つの処理の実行を待つ
package main
import "fmt"
// SlieceとChannelを扱う関数
func gorooutine1(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
// <- Channelに送信
c <- sum
}
func gorooutine2(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
// <- Channelに送信
c <- sum
}
func main() {
s := []int{1, 2, 3, 4, 5}
// channel integerを扱う
c := make(chan int)
go gorooutine1(s, c)
go gorooutine2(s, c)
// <- c でChannelから受け取るまで待機
x := <-c
fmt.Println(x)
y := <-c
fmt.Println(y)
}
15
15
Bufferd channel
package main
import "fmt"
func main() {
ch := make(chan int, 2)
ch <- 100
fmt.Println(len(ch))
ch <- 200
fmt.Println(len(ch))
// rangeで呼び出す場合はcloseしないと次のChannelを呼ぼうとしてエラーになる
close(ch)
// forで1つづつ呼び出す
for c := range ch {
fmt.Println(c)
}
}
1
2
100
200
channelのrange、Close
package main
import "fmt"
func goroutine1(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
c <- sum
}
// 処理完了後はcloseを入れる
close(c)
}
func main() {
s := []int{1, 2, 3, 4, 5}
c := make(chan int, len(s))
go goroutine1(s, c)
// channelを1回ずつ呼び出す
for i := range c {
fmt.Println(i)
}
}
1
3
6
10
15
Producer Consumer
package main
import (
"fmt"
"sync"
"time"
)
func producer(ch chan int, i int) {
// Something
ch <- i * 2
}
func consumer(ch chan int, wg *sync.WaitGroup) {
for i := range ch {
func() {
fmt.Println("process", i*1000)
wg.Done()
}()
}
fmt.Println("#################################")
}
func main() {
var wg sync.WaitGroup
ch := make(chan int)
// Producer
for i := 0; i < 10; i++ {
wg.Add(1)
go producer(ch, i)
}
// Consumer
go consumer(ch, &wg)
wg.Wait()
close(ch)
time.Sleep(2 * time.Second)
fmt.Println("Done")
}
process 0
process 4000
process 2000
process 6000
process 8000
process 10000
process 12000
process 14000
process 16000
process 18000
#################################
Done
fan-out fan-in
package main
import "fmt"
func producer(first chan int) {
defer close(first)
for i := 0; i < 10; i++ {
first <- i
}
}
func multi2(first chan int, second chan int) {
defer close(second)
for i := range first {
// 1 * 2 = 2
// 2 * 2 = 4
second <- i * 2
}
}
func multi4(second chan int, third chan int) {
defer close(third)
for i := range second {
// 2 * 4 = 8
// 4 * 4 = 4
third <- i * 4
}
}
func main() {
first := make(chan int)
second := make(chan int)
third := make(chan int)
go producer(first)
go multi2(first, second)
go multi4(second, third)
for result := range third {
fmt.Println(result)
}
}
0
8
16
24
32
40
48
56
64
72
select
package main
import (
"fmt"
"time"
)
func goroutine1(ch chan string) {
for {
ch <- "packat from 1"
time.Sleep(3 * time.Second)
}
}
func goroutine2(ch chan string) {
for {
ch <- "packat from 2"
time.Sleep(1 * time.Second)
}
}
func main() {
c1 := make(chan string)
c2 := make(chan string)
go goroutine1(c1)
go goroutine2(c2)
for {
select {
case msg1 := <-c1:
fmt.Println(msg1)
case msg2 := <-c2:
fmt.Println(msg2)
}
}
}
packat from 1
packat from 2
packat from 2
packat from 2
packat from 1
packat from 2
packat from 2
packat from 2
Default Section
package main
import (
"fmt"
"time"
)
func main() {
tick := time.Tick(100 * time.Millisecond)
boom := time.After(500 * time.Millisecond)
for {
select {
// 100Millisocond毎
case <-tick:
fmt.Println("tick,")
// 500Millisocond毎
case <-boom:
fmt.Println("BOOM")
// loop終了
return
// それ以外はピリオド
default:
fmt.Println(" .")
time.Sleep(50 * time.Millisecond)
}
}
}
.
.
tick,
.
.
tick,
.
.
tick,
.
.
tick,
.
.
tick,
BOOM