在下面这个示例中,定时器每 1 秒向 channel 发生一次消息。当数量达到 10 次时,会自动终止。

func main() {
    fmt.Println("Commencing countdown.")
    tick := time.Tick(1 * time.Second)
    for countdown := 10; countdown > 0; countdown-- {
        v := <-tick
        fmt.Println(countdown, v)
    }
}

file

但是,如果需要中途取消,则需要使用 select。
其格式如下:

select {
case <-ch1:
    // ...
case x := <-ch2:
    // ...use x...
case ch3 <- y:
    // ...
default:
    // ...
}

如果 select 中使用了 defalut,则要求在进入 select 中时,就需要有其中一个 case 准备好,否则一进入 select,就会执行 default 的代码。

select 只会被执行一次。

如果 select 中没有 default,并且在 进入 select 时,所有通道都没有内容,那么 select 就会阻塞。

经过改进,取消执行的代码示例如下:

package main

import (
    "bufio"
    "fmt"
    "os"
    "time"
)

func main() {
    stop := make(chan int)
    go tick(stop)
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Scan()
    stop <- 0
    fmt.Println("已结束")
}

func tick(stop chan int) {

    fmt.Println("Commencing countdown.")
    tick := time.Tick(1 * time.Second)

    for countdown := 10; countdown > 0; countdown-- {
        select {
        case v := <-tick:
            {
                fmt.Println(countdown, v)
                break
            }
        case <-stop:
            return
        }
    }
}