英文:
Golang persistent channel accepting input from multiple function calls
问题
我有一个函数 a
:
func a(input *some_type) {
// 做某事
b(input)
}
这个函数会被多次调用。
我想要一个函数 b
在从函数 a
收集到 n 个输入后无限期地等待,并在收集到输入后执行某个动作。
func b(input *some_type) {
// 等待直到收到 n 个输入,然后对所有输入执行某些操作
}
我应该如何实现这个功能?我最初的想法是在 a
和 b
之间使用一个带有通道的 sync.WaitGroup
。
英文:
I have a function a
:
func a(input *some_type) {
// do sth.
b(input)
}
This function gets called multiple times.
I want a function b
to wait indefinitely for input from function a
and perform an action when it has collected n inputs.
func b(input *some_type) {
// wait until received n inputs then do sth. with all inputs
}
How would I go about doing this? My first thought was to use a sync.WaitGroup
with a channel between a
and b
.
答案1
得分: 2
这是一个常见的生产者-消费者问题。使用通道来等待另一个例程的输入。像这样的东西有帮助吗?
在这个特定的例子中,你需要在收集输入后再次调用go b(c)
,因为它会终止,但你可以很容易地将b
所做的任何事情包装在一个无限的for
循环中。或者其他需要发生的事情。
请注意,在这个例子中,使用的是无缓冲的通道,这强制两个例程在同一时间相遇以“交接”*Thing
。如果你希望生产者(a
的过程)不必等待,你可以使用带缓冲的通道,创建方式如下:
c := make(chan(*Thing, n))
其中n
是通道可以存储的项目数。这允许生产者排队多个项目。
package main
import (
"fmt"
"time"
)
type Thing struct {
N int
}
func a(t *Thing, c chan (*Thing)) {
// stuff happens. whee
c <- t
}
func b(c chan (*Thing)) {
things := []*Thing{}
for i := 0; i < 10; i++ {
t := <-c
things = append(things, t)
fmt.Printf("I have %d things\n", i+1)
}
fmt.Println("I now have 10 things! Let's roll!")
// do stuff with your ten things
}
func main() {
fmt.Println("Hello, playground")
c := make(chan (*Thing))
go b(c)
// this would probably be done producer-consumer like in a go-routine
for i := 0; i < 10; i++ {
a(&Thing{i}, c)
time.Sleep(time.Second)
}
time.Sleep(time.Second)
fmt.Println("Program finished")
}
链接:https://play.golang.org/p/X14_QsSSU4
英文:
This is a common producer-consumer problem. Use channels to wait on the input from another routine. Does something like this help?
In this particular example, you would have to call go b(c)
again after collecting the inputs as it terminates, but you could easily wrap whatever b
does in an infinite for
loop. Or whatever needs to happen.
Please note that in this example, and unbuffered channel
is used, which forces both routines to meet at the same time to "hand off" the *Thing
. If you want the producer (a
's process) to not have to wait, you can use a buffered channel, which is created like so:
c := make(chan(*Thing, n))
Where n
is the number of items the channel can store. This allows several to be queued by the producer.
https://play.golang.org/p/X14_QsSSU4
package main
import (
"fmt"
"time"
)
type Thing struct {
N int
}
func a(t *Thing, c chan (*Thing)) {
// stuff happens. whee
c <- t
}
func b(c chan (*Thing)) {
things := []*Thing{}
for i := 0; i < 10; i++ {
t := <-c
things = append(things, t)
fmt.Printf("I have %d things\n", i+1)
}
fmt.Println("I now have 10 things! Let's roll!")
// do stuff with your ten things
}
func main() {
fmt.Println("Hello, playground")
c := make(chan (*Thing))
go b(c)
// this would probably be done producer-consumer like in a go-routine
for i := 0; i < 10; i++ {
a(&Thing{i}, c)
time.Sleep(time.Second)
}
time.Sleep(time.Second)
fmt.Println("Program finished")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论