当前位置:  开发笔记 > 编程语言 > 正文

对于在n秒后中断的循环

如何解决《对于在n秒后中断的循环》经验,为你挑选了1个好方法。



1> icza..:

通过检查自开始以来经过的时间:

var i int
for start := time.Now(); time.Since(start) < time.Second; {
    i++
}

或者使用通过调用获取的"超时"通道time.After().使用select检查,如果时间到了,但你必须添加一个default分支所以这将是一个非阻塞检查.如果时间到了,请从循环中断开.同样非常重要的是使用标签并从for循环中断,否则break将从中断,select它将是无限循环.

loop:
    for timeout := time.After(time.Second); ; {
        select {
        case <-timeout:
            break loop
        default:
        }
        i++
    }

注意:如果循环体还执行通信操作(如发送或接收),则使用超时通道可能是唯一可行的选项!(您可以在同一列表中列出超时检查和循环的通信操作select.)

我们可能会重写超时通道解决方案而不使用标签:

for stay, timeout := true, time.After(time.Second); stay; {
    i++
    select {
    case <-timeout:
        stay = false
    default:
    }
}

优化

我知道你的循环只是一个例子,但如果循环只做了一点点的工作,那么在每次迭代中都不值得检查超时.我们可能会重写第一个检查超时的解决方案,例如每10次迭代,如下所示:

var i int
for start := time.Now(); ; {
    if i % 10 == 0 {
        if time.Since(start) > time.Second {
            break
        }
    }
    i++
}

我们可以选择一个2的倍数的迭代次数,然后我们可以使用比剩余检查更快的位掩码:

var i int
for start := time.Now(); ; {
    if i&0x0f == 0 { // Check in every 16th iteration
        if time.Since(start) > time.Second {
            break
        }
    }
    i++
}

我们也可以计算一次结束时间(当循环必须结束时),然后你只需要比较当前时间:

var i int
for end := time.Now().Add(time.Second); ; {
    if i&0x0f == 0 { // Check in every 16th iteration
        if time.Now().After(end) {
            break
        }
    }
    i++
}

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有