1. time.After

假设业务中需调用服务接口A,要求超时时间为5秒,那么如何优雅、简洁的实现呢?

selecttime.After
package main

import (
	"fmt"
	"time"
)

//发送者
func sender(c chan int) {
	for i := 0; i < 20; i++ {
		c <- i
		if i >= 5 {
			time.Sleep(time.Second * 7)
		} else {
			time.Sleep(time.Second)
		}
	}
}

func main() {
	c := make(chan int)
	go sender(c)
	timeout := time.After(time.Second * 3)
	for {
		select {
		case d := <-c:
			fmt.Println(d)
		case <-timeout:
			fmt.Println("执行定时操作任务")
		case dd := <-time.After(time.Second * 3):
			fmt.Println(dd.Format("2006-01-02 15:04:05"), "执行超时动作")
		}
		fmt.Println("for end")
	}
}

2. time.NewTimer

NewTimer 创建一个 Timer,它会在最少过去时间段 d 后到期,向其自身的 C 字段发送当时的时间

 t.Reset()需要重置Reset 使 t 重新开始计时

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.NewTimer(time.Second * 2)
	ch := make(chan bool)
	go func(t *time.Timer) {
		defer t.Stop()
		for {
			select {
			case <-t.C:
				fmt.Println("timer running....")
				// 需要重置Reset 使 t 重新开始计时
				t.Reset(time.Second * 2)
			case stop := <-ch:
				if stop {
					fmt.Println("timer Stop")
					return
				}
			}
		}
	}(t)
	time.Sleep(10 * time.Second)
	ch <- true
	close(ch)
	time.Sleep(1 * time.Second)
}

3. time.NewTicker

NewTicker 返回一个新的 Ticker,该 Ticker 包含一个通道字段,并会每隔时间段 d 就向该通道发送当时的时间。它会调整时间间隔或者丢弃 tick 信息以适应反应慢的接收者。如果d <= 0会触发panic。

ticker.Stop()关闭该 Ticker 可以释放相关资源。

package main

import (
	"fmt"
	"time"
)

func main() {
	ticker := time.NewTicker(2 * time.Second) // 新建一个Ticker
	ch := make(chan bool)
	go func(ticker *time.Ticker) {
		defer ticker.Stop() // 停止Ticker
		for {
			select {
			case <-ticker.C: // Ticker.C 的封装
				fmt.Println("Ticker running...")
			case stop := <-ch:
				if stop {
					fmt.Println("Ticker Stop")
					return
				}
			}
		}
	}(ticker)
	time.Sleep(10 * time.Second)
	ch <- true
	close(ch)
}