zoukankan      html  css  js  c++  java
  • Golang之select中time.After()为什么不生效

    今天下午写bug的时候写了这样一个demo:

    func test() error {
    	ticker := time.NewTicker(time.Millisecond * 10)
    	defer ticker.Stop()
    
    	for {
    		select {
    			case <- ticker.C: // case1: 执行这个
    				if ok() {
    					fmt.Println("done")
    					return nil
    				}
    				fmt.Println("continue")
    			case <- time.After(time.Millisecond * 100): // case2: 这个永远不会被执行到
    				return errors.New("time out")
    		}
    	}
    }
    
    func ok() bool {
    	t := rand.Intn(3)
    	if t == 0 {
    		return true
    	}
    
    	return false
    }
    

    渴望的逻辑是执行case1数次之后如果一直不ok,就执行case2超时退出。

    结果多次测试发现case2time.After()一直执行不到,上下求索之后得出结论如下:

    每次执行time.After()都会创建一个新的timerchannel,而select语句是不可能记住它上次迭代的channel的。即case2time.After()只在本次select时有效,下次select又重新从下次selecttime.Now()开始计时了。(而且这种方式把一个异步操作变成了忙循环,违背了select语句的初衷。)

    所以正确的操作应该是:

    func test() error {
    	ticker := time.NewTicker(time.Millisecond * 10)
    	defer ticker.Stop()
    
            timer := time.After(time.Millisecond * 100) // timer
    	for {
    		select {
    			case <- ticker.C:
    				if ok() {
    					fmt.Println("done")
    					return nil
    				}
    				fmt.Println("continue")
    			case <- timer: // 改这里
    				return errors.New("time out")
    		}
    	}
    }
    

    来源

    Each time you execute time.After(4 * time.Second) you create a new timer channel. There's no way the select statement can remember the channel it selected on in the previous iteration. You've also taken what was an asynchronous operation and turned it into a busy loop, defeating the purpose of the select statement.

    https://stackoverflow.com/questions/39212333/how-can-i-use-time-after-and-default-in-golang

    需要写明的是,并非所有select中的time.After()都不生效,只是针对类似这种select有多个case可选的情况

  • 相关阅读:
    代码艺术 CountDownTimer
    java 正则
    What are the top 10 things that we should be informed about in life
    java 闭包与回调
    Hive记录-单机impala配置
    Hbase记录-Hbase介绍
    Hbase记录-Hbase其他工具
    Hbase记录-Hbase shell使用命令
    Hbase记录-Hbase Web管理工具
    CM记录-Hadoop运维管理
  • 原文地址:https://www.cnblogs.com/GaiHeiluKamei/p/13815550.html
Copyright © 2011-2022 走看看