Go语言Channel的一些Tips

基础知识

Golang中的Channel是一个类似于管道的类型,我们可以通过Channel来在不同的Goroutine之间传递数据。

创建Channel:ch := make(chan int)ch := make(chan int, 10)

前者是不带缓冲区的Channel,后者是带缓冲区的Channel。区别在于不带缓冲区的Channel在Send操作后会一直阻塞直到数据被Receive,而带缓冲区的Channel在缓冲区被填满之前都不会阻塞

Send操作:ch <- 1
Receive操作:i := <-ch
关闭操作:close(ch)

Tip1:关闭后Channel的行为

在Channel被执行关闭操作后,继续执行Send操作会导致panic: send on closed channel,而继续执行Receive操作还可以读到Channel中的数据,所有数据读取完后会不断地读到该类型默认初始化的值(如果类型为int则读到0,类型为bool则读到false)。

Tip2:控制退出

该Channel所在的Goroutine在另一个Goroutine执行quit <- true时退出。

1
2
3
4
5
6
7
8
for {
select {
case x := <-ch:
doSomething()
case <-quit:
quit()
}
}

Tip3:控制超时

该Channel所在的Goroutine在等待时间t后ch仍然未接收到数据时退出。

1
2
3
4
5
6
7
8
for {
select {
case x := <-ch:
doSomething()
case <-time.After(t):
timeout()
}
}

Tip4:清空缓冲区

假如ch中已经有数据了,可以使用下面的代码来清空缓冲区。如果ch中没有数据则直接执行后面的代码。

1
2
3
4
select {
case <-ch:
default:
}

Tip5:定时器

下面的代码会阻塞当前Goroutine一秒。

1
2
t := time.NewTimer(time.Second)
<-t.C

还可以使用t.Stop()操作来停止这个定时器。