如何让多个对象从一个go子程序中获取数据
How to allow multiple objects get data from a single go subroutine
我有一个案例,我想启动一个 go 子例程,它会定期从源中获取一些数据。如果调用失败,它将存储错误直到下一次调用成功。现在代码中有几个实例,其中一个实例将访问由 go 子例程提取的数据。我怎样才能实现这样的东西?
更新
我睡了一觉,喝了咖啡,我想我需要使用 java-ish 语义更连贯地重新表述问题。
我想出了一个基本的单例模式,returns 我是一个接口实现,它是 运行 一个永远循环内部的 go 子例程(让我们把永远循环的主要错误放在一边片刻)。问题是这个接口实现正被多个线程访问,以获取 go 子例程收集的数据。本质上,子程序每 10 分钟提取一次数据,然后无限次地请求数据。我怎样才能实现这样的东西?
您可以为此使用通道,但那样您将推送数据而不是拉取数据。我想那不会是个问题。
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 管理所有例程,否则您的程序将在所有例程完成之前结束。
编辑:关闭频道以停止 channel-read go-routine:
close(channelXY)
这是一个非常基本的示例,说明如何定期获取和收集数据。
请记住:运行这段代码不会像 main return 那样在任何事情真正发生之前不做任何事情,但是你如何处理它取决于你的具体用例。这段代码真的很简单,需要改进。这是部分问题的可能解决方案的草图:)
我在这里没有处理错误,但你可以像处理获取的数据一样处理它们(因此,多一个错误通道和一个从中读取的 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
}
我有一个案例,我想启动一个 go 子例程,它会定期从源中获取一些数据。如果调用失败,它将存储错误直到下一次调用成功。现在代码中有几个实例,其中一个实例将访问由 go 子例程提取的数据。我怎样才能实现这样的东西?
更新
我睡了一觉,喝了咖啡,我想我需要使用 java-ish 语义更连贯地重新表述问题。
我想出了一个基本的单例模式,returns 我是一个接口实现,它是 运行 一个永远循环内部的 go 子例程(让我们把永远循环的主要错误放在一边片刻)。问题是这个接口实现正被多个线程访问,以获取 go 子例程收集的数据。本质上,子程序每 10 分钟提取一次数据,然后无限次地请求数据。我怎样才能实现这样的东西?
您可以为此使用通道,但那样您将推送数据而不是拉取数据。我想那不会是个问题。
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 管理所有例程,否则您的程序将在所有例程完成之前结束。
编辑:关闭频道以停止 channel-read go-routine:
close(channelXY)
这是一个非常基本的示例,说明如何定期获取和收集数据。
请记住:运行这段代码不会像 main return 那样在任何事情真正发生之前不做任何事情,但是你如何处理它取决于你的具体用例。这段代码真的很简单,需要改进。这是部分问题的可能解决方案的草图:)
我在这里没有处理错误,但你可以像处理获取的数据一样处理它们(因此,多一个错误通道和一个从中读取的 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
}