本文共 1742 字,大约阅读时间需要 5 分钟。
目录
select 的语法和 switch 的语法很类似,它的执行顺序并不一定是按照我们代码的前后关系来决定的,而是满足哪个 case ,就执行这个 case 的结果。如果所有的 channel 都处于阻塞中,则走 default。
select {//从 channel 上等待一个消息case ret := <-retCh1: t.Logf("result:%s", ret)//从另一个 channel 上等待一个消息case ret := <-retCh2: t.Logf("result:%s", ret)//如果所有的 channel 都处于阻塞中,则走 defaultdefault: t.Error("No more returned")}
利用 select 的多路选择机制,我们可以实现一个超时机制,例如当某个 channel 多久后还没有消息返回,我们就返回超时。
time.After() 是在一段时间后,往 channel 里面发送一个消息,当没有达到设定的时间,这个 case 会被阻塞在这儿,当超过了我们设定的 duration 后,这个 case 就能从 channel 里面拿到数据,然后就可以用来做超时控制。
select {case ret := <-retCh1: t.Logf("result:%s", ret)case ret := <-time.After(time.Second * 5): t.Error("time out")}
package _selectimport ( "fmt" "testing" "time")func service() string { time.Sleep(time.Millisecond * 50) return "service执行完成"}func otherTask() { fmt.Println("otherTask的各种执行逻辑代码") time.Sleep(time.Millisecond * 100) fmt.Println("otherTask执行完成")}func syncService() chan string { //声明一个 channel, 数据存放只能为 string 类型 resCh := make(chan string) go func() { ret := service() fmt.Println("service 结果已返回") //因为不是用的 buffer channel, 所以,协程会被阻塞在这一步的消息传递过程中, //只有接受者拿到了 channel 中的消息,channel 放完消息后面的逻辑才会被执行。 resCh <- ret fmt.Println("channel 放完消息后面的逻辑") }() return resCh}//异步返回执行结果,先调用 SyncService(), 把它放入channel,用协程去执行,//然后主程序继续执行 otherTask(),最后吧 SyncService() 的返回结果//从 channel 里面取出来。func TestSyncService(t *testing.T) { select { case ret := <-syncService(): otherTask() t.Logf("result:%s", ret) case <-time.After(time.Millisecond * 10) : t.Error("time out") }}/*执行结果:=== RUN TestSyncService select_test.go:45: time out--- FAIL: TestSyncService (0.01s)FAIL*/
因为 service() 需要执行 0.05秒,我们设置了 0.01 秒就超时,所以就走了 time out。
注:这篇博文是我学习中的总结,如有转载请注明出处:
上一篇:
下一篇: