Golang持久通道接受来自多个函数调用的输入。

huangapple go评论69阅读模式
英文:

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 个输入,然后对所有输入执行某些操作
}

我应该如何实现这个功能?我最初的想法是在 ab 之间使用一个带有通道的 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 (
	&quot;fmt&quot;
	&quot;time&quot;
)

type Thing struct {
	N int
}

func a(t *Thing, c chan (*Thing)) {
	// stuff happens. whee
	c &lt;- t
}

func b(c chan (*Thing)) {
	things := []*Thing{}
	for i := 0; i &lt; 10; i++ {
		t := &lt;-c
		things = append(things, t)
		fmt.Printf(&quot;I have %d things\n&quot;, i+1)
	}
	fmt.Println(&quot;I now have 10 things! Let&#39;s roll!&quot;)
	// do stuff with your ten things
}

func main() {
	fmt.Println(&quot;Hello, playground&quot;)
	c := make(chan (*Thing))

	go b(c)

	// this would probably be done producer-consumer like in a go-routine
	for i := 0; i &lt; 10; i++ {
		a(&amp;Thing{i}, c)
		time.Sleep(time.Second)
	}
	time.Sleep(time.Second)
	fmt.Println(&quot;Program finished&quot;)
}

huangapple
  • 本文由 发表于 2017年4月8日 00:48:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/43283349.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定