目录
一、select 多路选择机制
1、selct 的语法格式
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 都处于阻塞中,则走 default
default:
t.Error("No more returned")
}
二、超时控制
利用 select 的多路选择机制,我们可以实现一个超时机制,例如当某个 channel 多久后还没有消息返回,我们就返回超时。
1、time.After()
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 _select
import (
"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。
注:这篇博文是我学习中的总结,如有转载请注明出处:
https://blog.csdn.net/DaiChuanrong/article/details/118312862
上一篇:Go-CSP并发机制
下一篇:Go-channel的关闭和广播