设想一下你在接收源源不断的数据,如果有700ms没有收到,则认为是一个超时,需要做出处理。
逻辑上可以设计一个grouting,里面放一个通道,每收到一条数据进行相应处理。通道中夹杂一个timer定时器的处理,若通道在700ms内有数据,则定时器被重置,重新等待700ms再调用定时器处理函数,否则,700ms时间到,运行定时器处理函数。示例代码如下:
Go
package main
import (
"fmt"
"runtime/debug"
"strings"
"time"
)
type demoSaveSuite struct {
chanDemoSave chan string
}
const dbSaveWaitDuration = 700 * time.Millisecond
func (s *demoSaveSuite) DemoHandler() {
go func() {
defer func() {
if r := recover(); r != nil {
fmt.Println(string(debug.Stack()))
}
}()
var timer *time.Timer
for sqlEntity := range s.chanDemoSave {
fmt.Printf("Received SQL entity: %s\n", sqlEntity)
// 检查 sqlEntity 是否包含 "SQL_Entity_5"
if strings.Contains(sqlEntity, "SQL_Entity_5") {
if timer != nil {
timer.Stop()
timer = nil // 将 timer 设为 nil 以确保不再使用它
continue // 跳过本次循环的后续部分
}
}
if timer == nil {
timer = time.AfterFunc(dbSaveWaitDuration, func() {
fmt.Printf("Executing action after delay for entity: %s\n", sqlEntity)
})
} else {
timer.Reset(dbSaveWaitDuration)
}
}
}()
}
func main() {
// You can place your main code here if needed
suite := &demoSaveSuite{
chanDemoSave: make(chan string, 5), // Buffer to avoid blocking when sending messages
}
go suite.DemoHandler()
// Send the first SQL entity
suite.chanDemoSave <- "SQL_Entity_1_300Millisecond"
time.Sleep(300 * time.Millisecond) // sleep a bit, but not enough for dbSaveWaitDuration
// Send the second SQL entity
suite.chanDemoSave <- "SQL_Entity_2_800Millisecond"
time.Sleep(800 * time.Millisecond) // let the timer expire for SQL_Entity_1
// Send the third SQL entity to test resetting the timer
suite.chanDemoSave <- "SQL_Entity_3_300Millisecond"
time.Sleep(300 * time.Millisecond) // sleep a bit, but not enough for dbSaveWaitDuration
// Send the fourth SQL entity
suite.chanDemoSave <- "SQL_Entity_4_800Millisecond"
time.Sleep(800 * time.Millisecond) // let the timer expire for SQL_Entity_3
// Send the fourth SQL entity
suite.chanDemoSave <- "SQL_Entity_5_2500Millisecond"
time.Sleep(2500 * time.Millisecond) // let the timer expire for SQL_Entity_3
// Close the channel
close(suite.chanDemoSave)
}
代码动行结果:
Go
Received SQL entity: SQL_Entity_1_300Millisecond
Received SQL entity: SQL_Entity_2_800Millisecond
Executing action after delay for entity: SQL_Entity_2_800Millisecond
Received SQL entity: SQL_Entity_3_900Millisecond
Received SQL entity: SQL_Entity_4_800Millisecond
Executing action after delay for entity: SQL_Entity_4_800Millisecond
Received SQL entity: SQL_Entity_5_2500Millisecond
Executing action after delay for entity: SQL_Entity_5_2500Millisecond
从运行结果看,只要超过700ms没有数据进入,就会引发定时器的回调,并且从2500ms的超时看只激发了一次,说明这里的定时器只会运行一次。没有超过700ms的,由于定时器被重置了,又开始等700ms才会运行,运行SQL_Entity_3时,定时器被删除,从结果看,虽然间隔是900ms远超700ms,依然定时器没有执行。接收到SQL_Entity_4时,由于timer已经为nil,因此又重新开启定时器