我如何等待通道活动的间歇来触发某些事情?

我有一个通道可以接收突发写入。我想等到通道上的突发发送完成后再触发操作。


我已经看过这个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

}

在我的情况下,我想等到在触发或发送输出之前不再在输入通道上为此突发发送任何数据。


我如何实现这一目标?


不负相思意
浏览 132回答 2
2回答

炎炎设计

听起来你需要在 goroutines 之间进行同步,也许沿着这条线。func main() {&nbsp; &nbsp; &nbsp; &nbsp; // Create a channel for our input&nbsp; &nbsp; &nbsp; &nbsp; input := make(chan int, 1)&nbsp; &nbsp; &nbsp; &nbsp; // Create another for synchronization between main and forked goroutines&nbsp; &nbsp; &nbsp; &nbsp; done := make(chan bool)&nbsp; &nbsp; &nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // block-wait for received value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <-input&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // do some more things here&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // when done, send signal to the main goroutine&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done <- true&nbsp; &nbsp; &nbsp; &nbsp; }()&nbsp; &nbsp; &nbsp; &nbsp; // Do something while wait for the forked goroutine&nbsp; &nbsp; &nbsp; &nbsp; // this block until `<-done`&nbsp; &nbsp; &nbsp; &nbsp; <-done&nbsp; &nbsp; &nbsp; &nbsp; close(mychan)}这篇文章非常清楚地解释了使用通道和同步组进行同步。

慕工程0101907

这就是我最终作为我的 debouncer 实现的:func Debounce(lull time.Duration, in chan struct{}, out chan struct{}) {&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; var last int64 = 0&nbsp; &nbsp; &nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case <-in:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; last = time.Now().Unix()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case <-time.Tick(lull):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if last != 0 && time.Now().Unix() >= last+int64(lull.Seconds()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; last = 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; out <- struct{}{}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }()}它需要一个间歇时间,即如果我们没有收到输入的持续时间,那么我们假设数据突发中存在中断。有2个通道,1个输入和1个输出。数据突发到达输入端,对于每个突发,我们在突发结束时写入输出通道。实现非常简单。每次从输入通道接收时,我只存储当前的 unix 时间戳。然后,我有一个停顿时间的自动收报机。所有这些都是检查我们是否已经超过了最后一次突发的等待时间。如果是这样,它会重置last为 0,并在输出通道上发出一个事件。下面是一些使用 debounce 函数的代码,它的静止时间为 2 秒,它在输入通道上发送随机突发:func main() {&nbsp; &nbsp; out := make(chan struct{})&nbsp; &nbsp; in := make(chan struct{})&nbsp; &nbsp; Debounce(2*time.Second, in, out)&nbsp; &nbsp; // Generating bursts of input data&nbsp; &nbsp; go func(in chan struct{}) {&nbsp; &nbsp; &nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case <-time.Tick(1 * time.Second):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; in <- struct{}{}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Sending!")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; shouldSleep := rand.Intn(2)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if shouldSleep == 1 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(5 * time.Second)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }(in)&nbsp; &nbsp; // Listening for output events&nbsp; &nbsp; go func(out chan struct{}) {&nbsp; &nbsp; &nbsp; &nbsp; for _ = range out {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Got an event!")&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }(out)&nbsp; &nbsp; // Do not let main terminate.&nbsp; &nbsp; done := make(chan struct{})&nbsp; &nbsp; <-done}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go