go里面关于超时的设计

设想一下你在接收源源不断的数据,如果有700ms没有收到,则认为是一个超时,需要做出处理。

逻辑上可以设计一个grouting,里面放一个通道,每收到一条数据进行相应处理。通道中夹杂一个timer定时器的处理,若通道在700ms内有数据,则定时器被重置,重新等待700ms再调用定时器处理函数,否则,700ms时间到,运行定时器处理函数。示例代码如下:

​
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)
}

​

代码动行结果:

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,因此又重新开启定时器

你可能感兴趣的:(Go,golang,xcode,开发语言)