是否有可能从Go中的一些goroutine中获得结果?

afe*_*par 3 concurrency go goroutine

我刚才刚刚了解了Google的编程语言Go.我对它提供的并发支持很感兴趣,并着手了解它的更多信息.但是,我去看看Go如何实现并发的特定功能,到目前为止我还没有看到任何证据表明这个功能完全存在.

这是一个假设的情况:假设我们正在编程一个函数来确定特定输入的Foo值.对于任何给定的输入,Foo值可以在域A或域B中找到(不在两者中).在这些域中搜索的技术是完全不同的,但它们共享成功搜索倾向于快速返回的属性,而不成功的搜索必须遍历整个数据集才能详尽无遗,因此需要很长时间.

现在,在其他采用并发的语言(例如Cilk)中,可以对Foosearch函数进行编程,以便生成Asearch函数和Bsearch函数.这些函数将同时运行,并且每当它们中的任何一个得到答案时,该答案将被报告给调用函数Foosearch,它将终止它已经生成但未返回的任何函数.

但是,使用Go的goroutines,看起来你只能通过一个频道连接两个例程 - 所以你无法设置Asearch或Bsearch可以发送的频道,具体取决于首先找到答案,并从中读取Foosearch它.它看起来你不能在没有阻塞的情况下从频道读取 - 所以你不能让Foosearch启动Asearch和Bsearch并从两者设置频道,然后在循环中运行检查是否有一个或哪个产生了一个答案.

我对Go的并发限制的理解是否正确?还有另一种方法可以达到给定的结果吗?

Bri*_*ell 16

不,我不相信你对Go限制的理解是正确的.

首先,我在Go中没有看到任何限制两个例程之间通信的渠道.您可以将同一个频道传递给Asearch和Bsearch,然后完成的任何一个都可以在该频道上发送结果.

如果你想使用两个通道,并等待其中一个获得结果,你可以使用该select语句.在Go教程中,选择用于发送请求的通道的示例,以及用于通知服务器退出的示例:

21    func server(op binOp, service chan *request, quit chan bool) {
22        for {
23            select {
24            case req := <-service:
25                go run(op, req);  // don't wait for it
26            case <-quit:
27                return;
28            }
29        }
30    }
Run Code Online (Sandbox Code Playgroud)

此外,虽然从通道接收通常阻止,您也可以从通道进行非阻塞接收.

如果在表单的赋值或初始化中使用了接收表达式

x, ok = <-ch
x, ok := <-ch
var x, ok = <-ch
Run Code Online (Sandbox Code Playgroud)

接收操作变为非阻塞.如果操作可以继续,则布尔变量ok将被设置为true并且值存储在x中; 否则ok设置为false,x设置为其类型的零值零值).

因此,有几种方法可以在不阻塞的情况下等待多个goroutine的结果.我想我会选择使用多路复用的多个通道select,因为这样你可以轻松地告诉哪个例程返回结果,而不必将这些信息打包到你发送的值或进行其他形式的带外通信.


Ran*_*ku' 5

您可以使用select关键字从多个渠道接收.

该值将取自结果早于其他通道的通道.

var c1, c2 chan int;
var result int;

select {
case result = <-c1:
    print("received ", result, " from c1\n");
case result = <-c2:
    print("received ", result, " from c2\n");
}
Run Code Online (Sandbox Code Playgroud)

参考