如何允许多个对象从单个 go 子例程获取数据



我有一个案例,我想启动一个go子例程,它将定期从源中获取一些数据。如果调用失败,它将存储错误,直到下一次调用成功。现在,代码中有几个实例,实例将访问由 go 子例程拉取的此数据。我怎样才能实现这样的东西?

更新

我睡了一会儿,喝了咖啡,我想我需要用java式的语义更连贯地重新表述这个问题。

我想出了一个基本的单例模式,它向我返回了一个接口实现,该接口实现在永久循环中内部运行 go 子例程(让我们暂时搁置永远循环的主要罪过)。问题是此接口实现被多个线程访问,以获取 go 子例程收集的数据。本质上,子例程每 10 分钟拉取一次数据,然后无限次请求。我怎样才能实现这样的东西?

下面是如何定期获取和收集数据的非常基本的示例。

请记住:运行此代码不会执行任何操作,因为在任何事情真正发生之前,main 将返回,但如何处理这取决于您的特定用例。这段代码确实是简陋的,需要改进。它是您问题的一部分的可能解决方案的草图:)

我在这里没有处理错误,但你可以像处理获取数据一样处理它们(所以,多一个错误,再读一个goroutine)。

func main() {
period := time.Second
respChan := make(chan string)
cancelChan := make(chan struct{})
dataCollection := []string
// periodicaly fetch data and send it to respChan
go func(period time.Duration, respChan chan string, cancelChan chan struct{}) {
ticker := time.Ticker(period)
for {
select {
case <-ticker.C:
go fetchData(respChan)
case <-cancelChan:
// close respChan to stop reading goroutine
close(respChan)
return
}
}
}(period, cancelChan)
// read from respChan and write to dataCollection
go func(respChan chan string) {
for data := range respChan {
dataCollection = append(dataCollection, data)
}
}(respChan)
// close cancelChan to gracefuly stop the app
// close(cancelChan)
}

func fetchData(respChan chan string) {
data := "fetched data"
respChan <- data
}

您可以使用通道来实现这一点,但随后您将推送数据而不是拉取数据。我想这不会有问题。

var channelXY = make(chan struct{}, 5000) //Change queue limits to your need, if push is much faster than pull you need to calculate the buffer
go func(channelXY <- chan struct{}) 
for struct{} := range channelXY {
//DO STUFF
}
WaitGroup.Done()
}(channelXY)
go func() {
channelXY <- struct{}
}

请记住使用WaitGroup管理所有例程,否则您的编程将在所有例程完成之前结束。

编辑:关闭通道以停止通道读取程序:

close(channelXY)

最新更新