简析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的区别及注意事项
- time.Ticker和time.Timer都属于定时器
- time.Ticker和time.Timer在使用之后都必须注意要关闭(stop),避免资源浪费
- 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语言学习笔记、语法知识、技术要点和个人理解及实战
网易游戏公司福利 555人发布