简析go语言channel与select结合使用的惯用法

go语言中channel和select结合使用可以实现多种功能。

1. 利用default分支避免阻塞

for  {
	select {
	case x := <-c:
		fmt.Println(x)
	default:
		...
	}
}

2.实现超时机制

// 使用time.After实现超时机制
select {
	case x := <-c:
		fmt.Println(x)
	case time.After(10 * time.Second):  // channel c阻塞10s后将执行该分支
		...
}
		
// 使用time.Timer实现超时机制
timer := time.NewTimer(10 * time.Second)
defer timer.Stop()

select {
	case x := <-c:
		fmt.Println(x)
	case <-timer.C:  // channel c阻塞10s后将执行该分支
		...
	}

3. 实现心跳机制

heartbeat := time.NewTimer(10 * time.Second)
defer heartbeat.Stop()

for {
	select {
	case x := <-c:
		fmt.Println(x)
	case <-heartbeat.C:  // 处理心跳逻辑
		...
	}
}

注:time.After, time.Timer, time.Ticker的区别及注意事项

  1. time.Ticker和time.Timer都属于定时器
  2. time.Ticker和time.Timer在使用之后都必须注意要关闭(stop),避免资源浪费
  3. time.Timer到固定时间后仅会执行一次,可以通过Reset方法来实现每隔固定时间执行
func main() {
	timer := time.NewTimer(1 * time.Second)
	defer timer.Stop()

	go func(t *time.Timer) {  // 仅执行一次该go routine就会退出
		<-t.C
		fmt.Println("do work...")
	}(timer)

	select {}
}

// 多次执行版本
func main() {
	timer := time.NewTimer(1 * time.Second)
	defer timer.Stop()

	go func(t *time.Timer) {
		for {
			<-t.C
			fmt.Println("do work...")
			t.Reset(1 * time.Second)  // 使用Rest方法重置定时器,实现多次执行。reset重新开始计时,如果调用时t还在等待中会返回true;如果t已经到期或者被停止了会返回false
		}
	}(timer)

	select {}
}

4.time.Ticker每隔固定时间都会触发,多次执行

func main() {
	timer := time.NewTicker(1 * time.Second)
	defer timer.Stop()

	go func(t *time.Ticker) {  // 该goroutine会多次执行
		for {
			<-t.C
			fmt.Println("do work...")
		}
	}(timer)

	select {}
}

$ go run ticker-case.go
do work...
do work...
do work...
...
do work...

5.time.After相当于time.Timer().C,最常用于和select channel结合使用实现超时机制

Go语言基础及实战 文章被收录于专栏

Go语言学习笔记、语法知识、技术要点和个人理解及实战

全部评论

相关推荐

点赞 评论 收藏
分享
牛客279957775号:铁暗恋
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务