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

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

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

问题

给你提供一些背景信息,

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

*Element通道类型是结构体。

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

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

elementInput := []string{FB_FRIENDS, BEAUTY_USERS, FITNESS_USERS, COMEDY_USERS}

wg.Add(len(elementInput))

for _, v := range elementInput {
    // 创建通道
    channel := make(chan *Element)
    // 并发调用
    go GetElements(ctx, page, channel)
    // 保持顺序

    var elementRes = <-channel
    if len(elementRes.List) > 0 {
        el = append(el, elementRes)
    }
}

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)

elementInput := []string{FB_FRIENDS, BEAUTY_USERS, FITNESS_USERS, COMEDY_USERS}

wg.Add(len(elementInput))

for _, v := range elementInput {
	//create channel
	channel := make(chan *Element)
	//concurrent call
	go GetElements(ctx, page, channel)
	//Preserve the order

	var elementRes = *&lt;-channel
	if len(elementRes.List) &gt; 0 {
		el = append(el, elementRes)
	}

}

wg.Wait()

答案1

得分: 4

你的实现不是并发的。

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

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

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

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

func main() {
	Concurrency()
	time.Sleep(2000)
}

func response(greeter string, channel chan *string) {
	reply := fmt.Sprintf("hello %s", greeter)
	channel <- &reply
}

func Concurrency() {
	events := []string{"ALICE", "BOB"}
	channels := make([]chan *string, 0)

	// 并发启动
	for _, event := range events {
		channel := make(chan *string)
		go response(event, channel)
		channels = append(channels, channel)
	}

	// 收集响应
	response := make([]string, len(channels))

	for i := 0; i < len(channels); i++ {
		response[i] = *<-channels[i]
	}

	// 打印响应
	log.Printf("channel response %v", response)
}
英文:

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

func main() {
	Concurrency()
	time.Sleep(2000)
}

func response(greeter string, channel chan *string) {
	reply := fmt.Sprintf(&quot;hello %s&quot;, greeter)
	channel &lt;- &amp;reply
}


func Concurrency() {
	events := []string{&quot;ALICE&quot;, &quot;BOB&quot;}
	channels := make([]chan *string, 0)

	// start concurrently 
	for _, event := range events {
		channel := make(chan *string)
		go response(event, channel)
		channels = append(channels, channel)
	}

	// collect response
	response := make([]string, len(channels))

	for i := 0; i &lt; len(channels); i++ {
		response[i] = *&lt;-channels[i]
	}
   // print response 
	log.Printf(&quot;channel response %v&quot;, response)
}

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:

确定