在Go语言中,我们如何在保持列表顺序的同时应用并发调用?

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

In Go, how do we apply concurrency calls while preserving the order of the list?

问题

给你提供一些背景信息,

变量elementInput是动态的。我不知道它的确切长度。
它可以是10、5等等。

*Element通道类型是结构体。

我的示例是有效的。但我的问题是这个实现仍然是同步的,因为我正在等待通道返回,以便我可以将其附加到我的结果中。

请问你能帮我如何并发调用GetElements()函数并保留elementInput中定义的顺序(基于索引)吗?

  1. elementInput := []string{FB_FRIENDS, BEAUTY_USERS, FITNESS_USERS, COMEDY_USERS}
  2. wg.Add(len(elementInput))
  3. for _, v := range elementInput {
  4. // 创建通道
  5. channel := make(chan *Element)
  6. // 并发调用
  7. go GetElements(ctx, page, channel)
  8. // 保持顺序
  9. var elementRes = <-channel
  10. if len(elementRes.List) > 0 {
  11. el = append(el, elementRes)
  12. }
  13. }
  14. wg.Wait()
英文:

To give you context,

The variable elementInput is dynamic. I do not know the exact length of it.
It can be 10, 5, or etc.

The *Element channel type is struct

My example is working. But my problem is this implementation is still synchronized, because I am waiting for the channel return so that I can append it to my result

Can you pls help me how to concurrent call GetElements() function and preserve the order defined in elementInput (based on index)

  1. elementInput := []string{FB_FRIENDS, BEAUTY_USERS, FITNESS_USERS, COMEDY_USERS}
  2. wg.Add(len(elementInput))
  3. for _, v := range elementInput {
  4. //create channel
  5. channel := make(chan *Element)
  6. //concurrent call
  7. go GetElements(ctx, page, channel)
  8. //Preserve the order
  9. var elementRes = *&lt;-channel
  10. if len(elementRes.List) &gt; 0 {
  11. el = append(el, elementRes)
  12. }
  13. }
  14. wg.Wait()

答案1

得分: 4

你的实现不是并发的。

原因是在每个子程序调用之后,你都在等待结果,这使得它成为串行的。

以下是类似于你的流程的示例实现:

  • 调用并发方法,该方法并发调用函数。
  • 然后我们循环并收集每个调用的响应。
  • 主子程序休眠2秒。

在运行代码的Go Playground中查看示例应用程序-> Sample Application

  1. func main() {
  2. Concurrency()
  3. time.Sleep(2000)
  4. }
  5. func response(greeter string, channel chan *string) {
  6. reply := fmt.Sprintf("hello %s", greeter)
  7. channel <- &reply
  8. }
  9. func Concurrency() {
  10. events := []string{"ALICE", "BOB"}
  11. channels := make([]chan *string, 0)
  12. // 并发启动
  13. for _, event := range events {
  14. channel := make(chan *string)
  15. go response(event, channel)
  16. channels = append(channels, channel)
  17. }
  18. // 收集响应
  19. response := make([]string, len(channels))
  20. for i := 0; i < len(channels); i++ {
  21. response[i] = *<-channels[i]
  22. }
  23. // 打印响应
  24. log.Printf("channel response %v", response)
  25. }
英文:

Your implementation is not concurrent.

> Reason after every subroutine call you are waiting for result, that is making this serial

Below is Sample implementation similar to your flow

  • calling Concurreny method which calls function concurrently
  • afterwards we loop and collect response from every above call
  • main subroutine sleep for 2 seconds

Go PlayGround with running code -> Sample Application

  1. func main() {
  2. Concurrency()
  3. time.Sleep(2000)
  4. }
  5. func response(greeter string, channel chan *string) {
  6. reply := fmt.Sprintf(&quot;hello %s&quot;, greeter)
  7. channel &lt;- &amp;reply
  8. }
  9. func Concurrency() {
  10. events := []string{&quot;ALICE&quot;, &quot;BOB&quot;}
  11. channels := make([]chan *string, 0)
  12. // start concurrently
  13. for _, event := range events {
  14. channel := make(chan *string)
  15. go response(event, channel)
  16. channels = append(channels, channel)
  17. }
  18. // collect response
  19. response := make([]string, len(channels))
  20. for i := 0; i &lt; len(channels); i++ {
  21. response[i] = *&lt;-channels[i]
  22. }
  23. // print response
  24. log.Printf(&quot;channel response %v&quot;, response)
  25. }

huangapple
  • 本文由 发表于 2022年9月23日 18:35:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/73826449.html
匿名

发表评论

匿名网友

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

确定