• 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可选的情况

  • 相关阅读:
    MongoDB新存储引擎WiredTiger实现(事务篇)
    mongodb存储引擎WiredTiger
    WiredTiger 4.1.0 发布,MongoDB 存储引擎
    MongoDB存储引擎、索引 原
    MongoDB Wiredtiger存储引擎实现原理
    MongoDB 副本集
    MongoDB 聚合
    MongoDB 索引
    mongodb 开发规范
    MongoDB 基本操作 数据库、集合
  • 原文地址:https://www.cnblogs.com/GaiHeiluKamei/p/13815550.html
Copyright © 2020-2023  润新知