go里面关于超时的设计

设想一下你在接收源源不断的数据,如果有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,因此又重新开启定时器

相关推荐
Alive~o.05 分钟前
Go语言进阶&依赖管理
开发语言·后端·golang
花海少爷7 分钟前
第十章 JavaScript的应用课后习题
开发语言·javascript·ecmascript
手握风云-8 分钟前
数据结构(Java版)第二期:包装类和泛型
java·开发语言·数据结构
喵叔哟28 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生34 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
hopetomorrow1 小时前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
小牛itbull1 小时前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i1 小时前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
闲暇部落1 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
GIS瞧葩菜1 小时前
局部修改3dtiles子模型的位置。
开发语言·javascript·ecmascript