Goの学習メモ9
Goメモ
channels
goroutineを理解できず次の単元に来てしまった。
チャネル型について扱っているらしい。なんとなく理解できた
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) }
配列の4番目から6番目の文字を足してxに代入している。
go sum(s[:len(s)/2], c)
配列の1番目から3番目の文字を足してyに代入している。
go sum(s[len(s)/2:], c)
buffer
バッファを付与できるらしい。
メモ帳を作成したりするときに便利かも。
package main import "fmt" func main() { ch := make(chan int, 2) ch <- 1 ch <- 2 fmt.Println(<-ch) fmt.Println(<-ch) }
バッファを2より少なくするとエラーになる。
ch := make(chan int, 1)
$ go run buffered-channels.go fatal error: all goroutines are asleep - deadlock!
close
チャネルはcloseできるらしい。
fibonacci関数が終了したらcloseしてc(xの値をかえしている。)
それをfor文で回している感じ。
package main import ( "fmt" ) func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } close(c) } func main() { c := make(chan int, 10) go fibonacci(cap(c), c) for i := range c { fmt.Println(i) } }
select
selectを使うことでgoroutine結果を使ってcase文で判断させることができる?(あまり理解していない)
package main import "fmt" func fibonacci(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 }() fibonacci(c, quit) }
selectはdefaultを使うことができる。
package main import ( "fmt" "time" ) func main() { tick := time.Tick(100 * time.Millisecond) boom := time.After(500 * time.Millisecond) for { select { case <-tick: fmt.Println("tick.") case <-boom: fmt.Println("BOOM!") return default: fmt.Println(" .") time.Sleep(50 * time.Millisecond) } } }
.が2回表示されたあとにtickが表示され。
0.005か0.0005秒かぐらいにBOOM!が表示される。
tick := time.Tick(100 * time.Millisecond) boom := time.After(500 * time.Millisecond) for { select { case <-tick: fmt.Println("tick.") case <-boom: fmt.Println("BOOM!") return default: fmt.Println(" .") time.Sleep(50 * time.Millisecond) } }
sync.Mutex
排他制御ができるらしい。
ただ現時点では難しくてわからない。
package main import ( "fmt" "sync" "time" ) type SafeCounter struct { v map[string]int mux sync.Mutex } func (c *SafeCounter) Inc(key string) { c.mux.Lock() c.v[key]++ c.mux.Unlock() } func (c SafeCounter) Value(key string) int { c.mux.Lock() defer c.mux.Unlock() return c.v[key] } func main() { c := SafeCounter{v: make(map[string]int)} for i := 0; i < 1000; i++ { go c.Inc("somekey") } time.Sleep(time.Second) fmt.Println(c.Value("somekey")) }
これで一通りはa tour of goの内容は終わり。
理解の甘い部分がかなりあるので別の教材で補填していく。