检查是否有人从go频道阅读了

时间:2019-04-12 09:58:41

标签: go channel

我们如何在go频道上设置诸如监听器之类的功能,以便当有人从该频道中读取某些内容时通知我们?

想象一下,我们有一个sequence number的频道条目,当有人从我们包装中某处的频道中读取某个值时,我们想将其递减。

3 个答案:

答案 0 :(得分:1)

未缓冲的通道同步传递数据,因此您已经知道何时读取数据。当缓冲区已满时,缓冲通道的工作方式类似,但是否则它们不会阻塞相同的通道,因此这种方法不会告诉您完全相同的事情。根据您的实际需求,还考虑使用sync.WaitGroup之类的工具。

ch = make(chan Data)
  ⋮
for {
      ⋮
    // make data available
    ch <- data

    // now you know it was read
    sequenceNumber--
      ⋮
}

答案 1 :(得分:1)

您可以创建通道中继机制,以实时捕获读取事件。

例如:

func relayer(in <-chan MyStruct) <-chan MyStruct {
        out := make(chan MyStruct) // non-buffered chan (see below)

        go func() {     
                defer close(out)
                readCountLimit := 10

                for item := range in {
                        out <- item
                        // ^^^^ so this will block until some worker has read from 'out'
                        readCountLimit--
                }
        }()     
        return out      
}

用法:

type MyStruct struct {
        // put your data fields here
}

ch := make(chan MyStruct) // <- original channel - used by producer to write to

rch := relayer(ch) // <- relay channel - used to read from

// consumers
go worker("worker 1", rch)
go worker("worker 2", rch)

// producer
for { ch <- MyStruct{} }

答案 2 :(得分:0)

您可以在手动模式下进行操作。在邮件中实现某种ACK标记。 像这样:

type Msg struct {
    Data int
    ack  bool
}

func (m *Msg) Ack() {
    m.ack = true
}

func (m *Msg) Acked() bool {
    return m.ack
}

func main() {
    ch := make(chan *Msg)
    msg := &Msg{Data: 1}
    go func() {
        for {
            if msg.Acked() {
                // do smth
            }
            time.Sleep(10 * time.Second)
        }
    }()
    ch <- msg

    for msg := range ch {
        msg.Ack()
    }
}

代码未经测试。 您还可以在Ack()方法中添加一些其他信息,例如关于package和func的元信息,从那里调用Ack(),此答案可能与以下内容有关:https://stackoverflow.com/a/35213181/3782382