ゴルーチン - meruneru/tech_memo GitHub Wiki

A tour of Go チュートリアル

Goroutines1/11

package main

import (
	"fmt"
	"time"
)

func say(s string) {
	for i := 0; i < 2; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	go say("go")
	say("hello")
}

実行結果は、goとhelloの順番がばらばらで表示される。

go                                 
hello 
go   
hello

Channels 2/11

チャネルを介して、ゴルーチン間で値を渡している。

package main

import (
	"fmt"
)

func sum(s []int, c chan int) {
	sum := 0

	for _, v := range s {
		sum += v
	}
	c <- sum
}

func main() {
	s := []int{7, 2, 8, -9, 4, 0}

	c := make(chan int)

	go sum(s[:len(s)/2], c)
	go sum(s[len(s)/2:], c)

	x, y := <-c, <-c

	fmt.Println(x, y, x+y)
}

Buffered Channels 3/11

package main

import (
	"fmt"
)

func main() {
	ch := make(chan int, 2)
	ch <- 1
	ch <- 2
	// ch <- 3 これがあると、バッファが詰まるからエラーとなる
	
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}

Range and Close 4/11

受信側の第2パラメータで、送信側がチャネルをクローズしたかわかる。 送信側がチャネルをクローズするとokがfalseとなる。

v, ok = <- ch

また、受信側がrangeで繰り返し受信している場合、 送信側がクローズするまで待ち続ける。

package main

import (
	"fmt"
)

func fibo(n int, ch chan int) {
	x, y := 0, 1

	for i := 0; i < n; i++ {
		ch <- x
		x, y = y, x+y
	}
	close(ch)
}

func main() {
	ch := make(chan int, 10)
	go fibo(cap(ch), ch)

	for i := range ch { //送信側チャネルがcloseするまで受信する
		fmt.Println(i)
	}
}

Select 5/11

メインスレッドからのデータをgoルーチンで値を受信して、 受信し終えたら、quitチャネルでメインスレッドに知らせる。

package main

import (
	"fmt"
)

func fibo2(c, quit chan int) {
	x, y := 0, 1
	for {
		select {
		case c <- x:
			x, y = y, x+y
		case <-quit:
			fmt.Println("quit")
			return
		}
	}

}

func main() {
	c := make(chan int)
	quit := make(chan int)
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println(<-c)
		}
		quit <- 0
	}()
	fibo2(c, quit)
}

Default Select 6/11

  • <-cで、cからの受信
  • c<-で、cへの送信
package main

import (
	"fmt"
	"time"
)

func main() {
	tick := time.Tick(100 * time.Millisecond)
	boom := time.Tick(500 * time.Millisecond)

	for {
		select {
		case <-tick:
			fmt.Println("tick.")
		case <-boom:
			fmt.Println("BOOM!")
			return
		default:
			fmt.Println("   .")
			time.Sleep(50 * time.Millisecond)
		}
	}
}
⚠️ **GitHub.com Fallback** ⚠️