select
参考 https://draveness.me/golang/docs/part2-foundation/ch05-keyword/golang-select/
Go 语言中的 select 关键字能够让 Goroutine 同时等待多个 Channel 的可读或者可写,在多个 Channel 发生状态改变之前,select 会一直阻塞当前线程或者 Goroutine。
当我们在 Go 语言中使用 select 控制结构时,会遇到两个有趣的现象:
- select 能在 Channel 上进行非阻塞的收发操作;
- select 在遇到多个 Channel 同时响应时会随机挑选 case 执行;
阻塞的情况
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 } } }
非阻塞的实际情况
errCh := make(chan error, len(tasks) wg := sync.WaitGroup{} wg.Add(len(tasks)) for i := range tasks { go func() { defer wg.Done() if err := tasks[i].Run(); err != nil { errCh <- err } }() } wg.Wait() select { case err := <-errCh: return err default: return nil }
在上面这段代码中,我们不关心到底多少个任务执行失败了,只关心是否存在返回错误的任务,最后的 select 语句就能很好地完成这个任务。