我有一个通道会收到一连串的写入信息。我想等到通道上的一连串发送完成后再触发一个动作。
我查看了这个gist,但是,如果缓冲区中有数据,它将每隔interval
发送一次输出:
func debounceChannel(interval time.Duration, output chan int) chan int {
input := make(chan int)
go func() {
var buffer int
var ok bool
// We do not start waiting for interval until called at least once
buffer, ok = <-input
// If channel closed exit, we could also close output
if !ok {
return
}
// We start waiting for an interval
for {
select {
case buffer, ok = <-input:
// If channel closed exit, we could also close output
if !ok {
return
}
case <-time.After(interval):
// Interval has passed and we have data, so send it
output <- buffer
// Wait for data again before starting waiting for an interval
buffer, ok = <-input
if !ok {
return
}
// If channel is not closed we have more data and start waiting for interval
}
}
}()
return input
}
在我的情况下,我想等到在触发或发送输出之前,该突发的输入通道上不再有任何数据被发送。
我如何实现这一目标?
答案 0 :(得分:1)
听起来你需要在goroutines之间进行同步,也许是沿着这条线。
func main() {
// Create a channel for our input
input := make(chan int, 1)
// Create another for synchronization between main and forked goroutines
done := make(chan bool)
go func() {
// block-wait for received value
<-input
// do some more things here
// when done, send signal to the main goroutine
done <- true
}()
// Do something while wait for the forked goroutine
// this block until `<-done`
<-done
close(mychan)
}
这个post解释了使用频道和同步组的同步。
答案 1 :(得分:0)
这是我最终实施的辩护人:
func Debounce(lull time.Duration, in chan struct{}, out chan struct{}) {
go func() {
var last int64 = 0
for {
select {
case <-in:
last = time.Now().Unix()
case <-time.Tick(lull):
if last != 0 && time.Now().Unix() >= last+int64(lull.Seconds()) {
last = 0
out <- struct{}{}
}
}
}
}()
}
这需要一个暂停时间,即如果我们没有收到输入的持续时间,那么我们假设数据突发中断。有2个通道,1个输入和1个输出。数据突发到达输入端,对于每个突发,我们在突发结束时写入输出通道。
实施非常简单。我只是在每次从输入通道收到时存储当前的unix时间戳。然后,我有一个滴答作响的持续时间。所有这一切都是检查我们是否超过了最后一次爆发的等待时间。如果是,则将last
重置为0,以便在输出通道上发出事件。
这里有一些代码使用去抖功能,间隔时间为2秒,在输入通道上发送随机突发:
func main() {
out := make(chan struct{})
in := make(chan struct{})
Debounce(2*time.Second, in, out)
// Generating bursts of input data
go func(in chan struct{}) {
for {
select {
case <-time.Tick(1 * time.Second):
in <- struct{}{}
fmt.Println("Sending!")
shouldSleep := rand.Intn(2)
if shouldSleep == 1 {
time.Sleep(5 * time.Second)
}
}
}
}(in)
// Listening for output events
go func(out chan struct{}) {
for _ = range out {
fmt.Println("Got an event!")
}
}(out)
// Do not let main terminate.
done := make(chan struct{})
<-done
}