# select中的超时优先级
> select中可以通过在case设置time.After进行超时,但为什么超时操作会比其他的case优先级低?如果其他的case会运行那么超时就不作数。为此我在主协程模拟了一个超时
```go
func main() {
channel := make(chan interface{}, 100)
delay := make(chan interface{})
for i := 0; i < 10; i++ {
channel <- 1
}
go func() {
for {
select {
case <-delay:
fmt.Println("超时")
case i := <-channel:
fmt.Println(i)
time.Sleep(time.Second)
}
}
}()
time.After(3 * time.Second)
delay <- 1
for {
}
}
```
结果打印如下
```
1
超时
1
1
1
1
1
1
```
* 这样的结果很符合我对"超时"的认知,函数的超时只取决于调用者本身而不是取决于函数中的状态。
---
> 而正常的select却不是这样的,我做了这样的对比只是印证了time.After内部的实现原理与我写的不一样
查看源码可以发现time.After实际上是调用了NewTimer,NewTimer的源码是这样的
```go
func NewTimer(d Duration) *Timer {
c := make(chan Time, 1)
t := &Timer{
C: c,
r: runtimeTimer{
when: when(d),
f: sendTime,
arg: c,
},
}
startTimer(&t.r)
return t
}
```
* 可以看出time.After其实是返回了NewTimer内部定义的Timer的C。
* 而我认为问题的关键就在于下面的startTimer,其中肯定有往C输入内容的管道。往C输入内容的时机就是问题的答案。
* 由于源码过于复杂比较难分析,因此想问问这个优先级的原因出在哪里?
我认为你的代码有2点问题: 第一,你的3秒超时效果并没有达到, 正确的用法是`tc := time.After(time.Second * 3); <-tc;delay <- 1` 第二, select那里, delay和channel都有数据的时候,select是随机选择一个执行,而不保证delay优先执行。你的channel是提前放入10个数据,实际运行的结果是不能保证到了超时就能打印“超时”
#1
更多评论
你的代码我愣是没看懂……
正常for中的select至少会有个分支进行return,以退出这个处理循环。
如果你要超时后不继续读数据的话
至少应该是
```go
go func() {
for {
select {
case <-delay:
fmt.Println("超时")
return
case i := <-channel:
fmt.Println(i)
time.Sleep(time.Second)
}
}
}()
```
#2