Goroutines – 将关键数据发送给单个 goroutine 并等待结果

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

Goroutines - send critical data to the single goroutine and wait for result

问题

我在我的应用程序中有许多goroutine在运行,我还有另一个goroutine必须在同一时间段内仅处理一个请求,然后将结果发送回调用者。

这意味着其他goroutine应该等待,直到必要的(单操作)goroutine忙碌。

[goroutine 1] <-
-
-
-
[goroutine 2]<- - - - -> [在单个goroutine中处理一些数据并将结果发送回调用者
-
-
-
[goroutine 3] <-

这是它应该看起来的示意图

我对Go语言非常非常陌生,对如何正确实现它了解甚少。

有人能提供给我一些可运行的示例,这样我就可以在Go Playground上运行它吗?

英文:

I have many goroutines running in my application, and I have another goroutine that must handle only one request at the same period of time and then send the result back to caller.

It means other goroutines should wait until the necessary (single-operated) goroutine is busy.

[goroutine 1] &lt;-
                 -
                   -
                     -
[goroutine 2]&lt;- - - -  -&gt; [Process some data in a single goroutine and send the result back to caller
                     -
                   -
                 -
[goroutine 3] &lt;-

This is the diagram how it should look like

I'm very very new to Go and I have a poor knowledge how it should be correctly implemented.

> Could someone provide me with some working example so I can run it on go playground?

答案1

得分: 0

我将用一个goroutine来描述这个方法,它可以将两个数字相加。

为goroutine声明请求和响应类型。在请求中包含一个响应值的通道:

type request struct {
    a, b int          // 要相加的两个数字
    ch   chan response
}

type response struct {
    n int              // 相加结果
}

启动一个接收请求、执行操作并将响应发送到请求中的通道的goroutine:

func startAdder() chan request {
    ch := make(chan request)
    go func() {
        for req := range ch {
            req.ch <- response{req.a + req.b}
        }
    }()
    return ch
}

要相加这两个数字,向goroutine发送一个带有响应通道的请求。从响应通道接收响应值。返回响应值:

func add(ch chan request, a, b int) int {
    req := request{ch: make(chan response), a: a, b: b}
    ch <- req
    return (<-req.ch).n
}

使用方法如下:

ch := startAdder()
fmt.Println(add(ch, 1, 2))

在GoLang PlayGround上运行

英文:

I'll describe the approach with a goroutine that adds two numbers.

Declare request and response types for the goroutine. Include a channel of response values in the request:

type request struct {
	a, b  int          // add these two numbers
	ch chan response
}

type response struct {
	n int              // the result of adding the numbers
}

Kick off a goroutine that receives requests, executes the action and sends the response to the channel in the request:

func startAdder() chan request {
	ch := make(chan request)
	go func() {
		for req := range ch {
			req.ch &lt;- response{req.a + req.b}
		}
	}()
	return ch
}

To add the numbers, send a request to the goroutine with a response channel. Receive on the response channel. Return the response value.

func add(ch chan request, a, b int) int {
	req := request{ch: make(chan response), a: a, b: b}
	ch &lt;- req
	return (&lt;-req.ch).n
}

Use it like this:

ch := startAdder()
fmt.Println(add(ch, 1, 2))

Run it on the GoLang PlayGround.

答案2

得分: 0

这是一个代码片段,其中包含几个工作协程和一个处理器协程。只有一个工作协程可以向处理器发送数据,因为processorChannel只允许一个条目。当处理器完成工作后,它会将响应发送回给它接收工作的工作协程。

package main

import (
	"fmt"
	"time"
)

type WorkPackage struct {
	value           int
	responseChannel chan int
}

func main() {
	processorChannel := make(chan *WorkPackage)

	for i := 0; i < 3; i++ {
		go runWorker(processorChannel)
	}

	go runProcessor(processorChannel)

	// 在这里进行一些聪明的等待,比如使用等待组
	time.Sleep(5 * time.Second)
}

func runWorker(processorChannel chan *WorkPackage) {
	responseChannel := make(chan int)

	for i := 0; i < 10; i++ {
		processorChannel <- &WorkPackage{
			value:           i,
			responseChannel: responseChannel,
		}
		fmt.Printf("** 发送 %d\n", i)

		response := <-responseChannel
		fmt.Printf("** 收到响应 %d\n", response)

		// 做一些工作
		time.Sleep(300 * time.Millisecond)
	}
}

func runProcessor(processorChannel chan *WorkPackage) {
	for workPackage := range processorChannel {
		fmt.Printf("## 收到 %d\n", workPackage.value)

		// 做一些处理工作
		time.Sleep(100 * time.Millisecond)

		workPackage.responseChannel <- workPackage.value * 100
	}
}
英文:

Here a code snippet which has a few worker-goroutines and one processor-goroutine. Only one single worker-goroutine can send something to the processor because the the processorChannel only allows one entry. When the processor is done, he sends back the response to the worker he got the work from.

package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

type WorkPackage struct {
	value           int
	responseChannel chan int
}

func main() {
	processorChannel := make(chan *WorkPackage)

	for i := 0; i &lt; 3; i++ {
		go runWorker(processorChannel)
	}

	go runProcessor(processorChannel)

	// Do some clever waiting here like with wait groups
	time.Sleep(5 * time.Second)
}

func runWorker(processorChannel chan *WorkPackage) {
	responseChannel := make(chan int)

	for i := 0; i &lt; 10; i++ {
		processorChannel &lt;- &amp;WorkPackage{
			value:           i,
			responseChannel: responseChannel,
		}
		fmt.Printf(&quot;** Sent %d\n&quot;, i)

		response := &lt;-responseChannel
		fmt.Printf(&quot;** Received the response %d\n&quot;, response)

		// Do some work
		time.Sleep(300 * time.Millisecond)
	}
}

func runProcessor(processorChannel chan *WorkPackage) {
	for workPackage := range processorChannel {
		fmt.Printf(&quot;## Received %d\n&quot;, workPackage.value)

		// Do some processing work
		time.Sleep(100 * time.Millisecond)
		
		workPackage.responseChannel &lt;- workPackage.value * 100
	}
}

huangapple
  • 本文由 发表于 2022年7月19日 06:06:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/73029112.html
匿名

发表评论

匿名网友

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

确定