英文:
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] <-
-
-
-
[goroutine 2]<- - - - -> [Process some data in a single goroutine and send the result back to caller
-
-
-
[goroutine 3] <-
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))
英文:
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 <- 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 <- req
return (<-req.ch).n
}
Use it like this:
ch := startAdder()
fmt.Println(add(ch, 1, 2))
答案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 (
"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)
// 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 < 10; i++ {
processorChannel <- &WorkPackage{
value: i,
responseChannel: responseChannel,
}
fmt.Printf("** Sent %d\n", i)
response := <-responseChannel
fmt.Printf("** Received the response %d\n", response)
// Do some work
time.Sleep(300 * time.Millisecond)
}
}
func runProcessor(processorChannel chan *WorkPackage) {
for workPackage := range processorChannel {
fmt.Printf("## Received %d\n", workPackage.value)
// Do some processing work
time.Sleep(100 * time.Millisecond)
workPackage.responseChannel <- workPackage.value * 100
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论