为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
不负相思意 2021-12-20 19:07:05
我有一个通道可以接收突发写入。我想等到通道上的突发发送完成后再触发操作。我已经看过这个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}在我的情况下,我想等到在触发或发送输出之前不再在输入通道上为此突发发送任何数据。我如何实现这一目标?
查看完整描述

2 回答

?
炎炎设计

TA贡献1808条经验 获得超4个赞

听起来你需要在 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)

}

这篇文章非常清楚地解释了使用通道和同步组进行同步。


查看完整回答
反对 回复 2021-12-20
?
慕工程0101907

TA贡献1887条经验 获得超5个赞

这就是我最终作为我的 debouncer 实现的:


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,并在输出通道上发出一个事件。


下面是一些使用 debounce 函数的代码,它的静止时间为 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

}


查看完整回答
反对 回复 2021-12-20
  • 2 回答
  • 0 关注
  • 131 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信