在循环内将goroutine的结果传递给一个变量。

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

Pass a result from goroutine to a variable inside the loop

问题

在下面的代码中,如何将slowExternalFunction的结果分配给适当的person?可以通过通道来实现,为了清晰起见,我定义了slowExternalFunction返回int

type Person struct {
    Id        int
    Name      string
    WillDieAt int
}

func slowExternalAPI(i int) int {
    time.Sleep(10)
    willDieAt := i + 2040
    return willDieAt
}

func fastInternalFunction(i int) string {
    time.Sleep(1)
    return fmt.Sprintf("Ivan %v", i)
}

func main() {
    var persons []Person

    for i := 0; i <= 100; i++ {
        var person Person
        person.Id = i
        person.Name = fastInternalFunction(i)
        go func(i int) {
            result := slowExternalAPI(i)
            person.WillDieAt = result
        }(i)
        persons = append(persons, person)
    }
    fmt.Printf("%v", persons)
}

你可以在这里查看代码:https://play.golang.org/p/BRBgtH5ryo

英文:

At the code below how to assign a result from slowExternalFunction to a proper person? It can be done via channels and just for clarity I defined that slowExternalFunction returns int.

type Person struct {
	Id        int
	Name      string
	WillDieAt int
}

func slowExternalAPI(i int) int {
	time.Sleep(10)
	willDieAt := i + 2040
	return willDieAt 
}

func fastInternalFunction(i int) string {
	time.Sleep(1)
	return fmt.Sprintf(&quot;Ivan %v&quot;, i)
}

func main() {
	var persons []Person

	for i := 0; i &lt;= 100; i++ {
		var person Person
		person.Id = i
		person.Name = fastInternalFunction(i)
		go slowExternalAPI(i)
		person.WillDieAt = 2050 //should be willDieAt from the slowExternalAPI
		persons = append(persons, person)
	}
	fmt.Printf(&quot;%v&quot;, persons)
}

https://play.golang.org/p/BRBgtH5ryo

答案1

得分: 2

要使用通道来完成这个任务,你需要对代码进行相当大的重构。

最小的更改是在 goroutine 中进行赋值:

go func(){
    person.WillDieAt = slowExternalFunction(i)
}()

然而,为了使其工作,我们还需要进行其他一些更改:

  • 使用指针数组,以便在赋值完成之前就可以添加 person。
  • 实现一个等待组,以便在打印结果之前等待所有 goroutine 完成。

以下是带有这些更改的完整 main 函数:

func main() {
    var persons []*Person
    var wg sync.WaitGroup

    for i := 0; i <= 100; i++{
        person := &Person{}
        person.Id = i
        person.Name = fastInternalFunction(i)
        wg.Add(1)
        go func(){
            person.WillDieAt = slowExternalFunction(i)
            wg.Done()
        }()

        persons = append(persons,person)
    }
    wg.Wait()
    for _, person := range persons {
        fmt.Printf("%v ", person )
    }
}

Playground: https://play.golang.org/p/8GWYD29inC

英文:

To do it using channels you'll have to refactor your code quite a bit.

Smallest change would be to do the assignment in the goroutine:

go func(){
    person.WillDieAt = slowExternalFunction(i)
}()

However, to make this work we'd need to make some other changes as well:

  • Use an array of pointers so that you can add the person before the assignment finishes.
  • Implement a wait group so that you wait for all goroutines to finish before printing the results.

Here's the complete main function with the changes:

func main() {
    var persons []*Person
    var wg sync.WaitGroup

    for i := 0; i &lt;= 100; i++{
	    person := &amp;Person{}
	    person.Id = i
	    person.Name = fastInternalFunction(i)
	    wg.Add(1)
	    go func(){
	        person.WillDieAt = slowExternalFunction(i)
	        wg.Done()
	    }()

	    persons = append(persons,person)
    }
    wg.Wait()
    for _, person := range persons {
	    fmt.Printf(&quot;%v &quot;, person )
    }
}

Playground: https://play.golang.org/p/8GWYD29inC

huangapple
  • 本文由 发表于 2017年8月15日 08:49:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/45685024.html
匿名

发表评论

匿名网友

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

确定