ective_go.html#goroutines (https://golang.org/doc/e ective_go.html#goroutines) They're called goroutines because the existing terms—threads, coroutines, processes, and so on—convey inaccurate connotations. A goroutine has a simple model: it is a function executing concurrently with other goroutines in the same address space. It is lightweight, costing little more than the allocation of stack space. And the stacks start small, so they are cheap, and grow by allocating (and freeing) heap storage as required.
Do not communicate by sharing memory; instead, share memory by communicating. Google 翻訳 (Google%E7%BF%BB%E8%A8%B3) メモリを共有して通信してはいけません。かわりに、通信によってメモリを共有してくださ い。
func main() { ch := make(chan int) const n = 10 for i := 0; i < n; i++ { go func(i int) { ch <- i }(i) } for i := 0; i < n; i++ { fmt.Println(" 会 ", <-ch) } } Run
default 句があり、入出力が検知できなかったときに、default 句が直ちに実行される select { case v1 := <-c1: fmt.Printf("received %v from c1\n", v1) case v2 := <-c2: fmt.Printf("received %v from c2\n", v1) case c3 <- 23: fmt.Printf("sent %v to c3\n", 23) default: fmt.Printf("no one was ready to communicate\n") }
FanIn(input1, input2 <-chan string) <-chan string { c := make(chan string) go func() { for { select { case s := <-input1: c <- s case s := <-input2: c <- s } } }() return c } Run
import "fmt" func f(left, right chan int) { left <- 1 + <-right } func main() { const n = 10000 leftmost := make(chan int) right := leftmost left := leftmost for i := 0; i < n; i++ { right = make(chan int) go f(left, right) left = right } go func(c chan int) { c <- 1 }(right) fmt.Println(<-leftmost) } Run
"fmt" "sync" ) func main() { wg := new(sync.WaitGroup) for i := 0; i < 5; i++ { i := i wg.Add(1) go func() { fmt.Printf("hogehoge %d\n", i) wg.Done() }() } wg.Wait() } Run
DoSomething(c chan string) { for { select { case v := <-c: fmt.Println(v) case <-time.After(500 * time.Millisecond): fmt.Println("timed out") return } } } c := make(chan string, 10) go DoSomething(c) rand.Seed(time.Now().UnixNano()) for i := 0; i < 10; i++ { c <- " 会 " SleepRandam(200) } Run
DoSomething(c chan string) { timeout := time.After(500 * time.Millisecond) for { select { case v := <-c: fmt.Println(v) case <-timeout: fmt.Println("timed out") return } } } c := make(chan string, 10) go DoSomething(c) rand.Seed(time.Now().UnixNano()) for i := 0; i < 10; i++ { c <- " 会 " SleepRandam(200) } Run
time.Time { c := make(chan time.Time) go func() { tick := time.Tick(100 * time.Millisecond) for now := range tick { c <- now } }() return c } c := TickTack() for i := 0; i < 10; i++ { fmt.Println(<-c) } Run
Time { c := make(chan Time) go func() { tick0, tick1 := time.Tick(100*time.Millisecond), time.Tick(200*time.Millisecond) for { select { case t := <-tick0: c <- Time{t, "interval 100ms"} case t := <-tick1: c <- Time{t, "interval 200ms"} } } }() return c } c := TickTack() for i := 0; i < 10; i++ { t := <-c fmt.Println(t.msg, t.t) } Run
c = make(chan int) quit = make(chan bool) ) const n = 50 for i := 0; i < n; i++ { go LaunchWorker(c, quit) } for i := 0; i < n; i++ { quit <- true } func LaunchWorker(c chan int, quit chan bool) { for { select { case <-c: // do something case <-quit: return } } }
c = make(chan int) ctx, cancel = context.WithCancel(context.Background()) ) const n = 50 for i := 0; i < n; i++ { go LaunchWorker(ctx, c) } cancel() fmt.Println("That was refreshing") func LaunchWorker(ctx context.Context, c chan int) { for { select { case <-c: // do something case <-ctx.Done(): return } } }
string) { timeout := time.After(500 * time.Millisecond) for { select { case v := <-c: fmt.Println(v) case <-timeout: fmt.Println("timed out") return } } } c := make(chan string, 10) go DoSomething(c) rand.Seed(time.Now().UnixNano()) for i := 0; i < 10; i++ { c <- " 会 " SleepRandam(200) } Run
c chan string) { for { select { case v := <-c: fmt.Println(v) case <-ctx.Done(): fmt.Println("timed out") return } } } c := make(chan string, 10) ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() go DoSomething(ctx, c) rand.Seed(time.Now().UnixNano()) for i := 0; i < 10; i++ { c <- " 会 " SleepRandam(200) } Run
-race goroutine_patterns/race_condition.go ================== WARNING: DATA RACE Read at 0x000000101b38 by goroutine 6: main.main.func1() /.../go/src/github.com/Kooooya/slides/goroutine_patterns/race_condition.go:8 +0x3d Previous write at 0x000000101b38 by goroutine 5: main.main.func1() /.../go/src/github.com/Kooooya/slides/goroutine_patterns/race_condition.go:8 +0x59 Goroutine 6 (running) created at: main.main() /.../go/src/github.com/Kooooya/slides/goroutine_patterns/race_condition.go:9 +0x51 Goroutine 5 (finished) created at: main.main() /.../go/src/github.com/Kooooya/slides/goroutine_patterns/race_condition.go:9 +0x51 ================== Found 1 data race(s) exit status 66