Go语言channel超时处理教程
在 的通信过程中,经常会遇到超时问题,即向 写数据时发现 channel 已满,或者从 channel 试图读取数据时发现 channel 为空。如果不正确处理这些情况,很可能会导致整个 锁死。
Go语言channel超时场景
语法
name := <-chanName
说明
我们从管道 chanName 里面接受数据,并将接受到的数据存放到 name 中,如果我们的程序一直没有给管道 chanName 发送数据,那么上面的代码就会永久的阻塞。
那么,此时,如果没有合理的超时处理机制,这行代码很可能会导致整个进程阻塞。
Go语言channel超时处理
并没有为 channel 超时提供直接的解决方案,但我们可以利用 机制。虽然 select 机制不是专为超时而设计的,却能很方便地解决超时问题。
select 的特点是只要其中一个 case 已经完成,程序就会继续往下执行,而不会考虑其他 case 的情况。
案例
channel超时处理
使用 select 实现 channel 超时处理
package main import ( "fmt" "time" ) func main() { fmt.Println("嗨客网(www.haicoder.net)") ch := make(chan int) quit := make(chan bool) //新开一个协程 go func() { for { select { case num := <-ch: //如果有数据,下面打印。但是有可能ch一直没数据 fmt.Println("received num = ", num) case <-time.After(3 * time.Second): //上面的ch如果一直没数据会阻塞,那么select也会检测其他case条件,检测到后3秒超时 fmt.Println("TimeOut") quit <- true //写入 } } }() //别忘了() for i := 0; i < 3; i++ { ch <- i time.Sleep(time.Second) } <-quit //这里暂时阻塞,直到可读 fmt.Println("Over") }
程序运行后,控制台输出如下:
首先,我们使用 创建了一个 的管道 ch 和 quit,接着, 使用 go 创建了一个协程。
在协程里,我们使用 加上 select 语句,同时监听管道 ch 和 time 定时器,如果 3 秒钟管道 ch 没有接收到数据,那么此时会走到 time 分支,此时我们使用 quit 管道发送一条消息。
main 协程接收到 quit 消息,自动退出,通过 select 我们实现了管道的超时控制。
Go语言channel超时处理总结
在并发编程的通信过程中,经常会遇到超时问题,即向 channel 写数据时发现 channel 已满,或者从 channel 试图读取数据时发现 channel 为空。如果不正确处理这些情况,很可能会导致整个 goroutine 锁死。Go 语言 channel 超时场景:
name := <-chanName
我们从管道 chanName 里面接受数据,并将接受到的数据存放到变量 name 中,如果我们的程序一直没有给管道 chanName 发送数据,那么上面的代码就会永久的阻塞。
那么,此时,如果没有合理的超时处理机制,这行代码很可能会导致整个进程阻塞。