首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >动态创建goroutines的最佳方法是什么?

动态创建goroutines的最佳方法是什么?
EN

Stack Overflow用户
提问于 2014-11-07 16:25:30
回答 1查看 1.1K关注 0票数 2

对不起,如果这是个新问题,但我是新手。我有跟随操场。如何动态地创建我的大猩猩?我在操场上的第一组按预期工作,但第二组对每个值返回"11“。我可以通过取消第38行来解决这个问题,但这似乎有点像一次黑客攻击。有更好的方法来动态地创建我的猩猩吗?

代码语言:javascript
运行
复制
package main

import (
    "fmt"
    "log"
    "time"
)

func myFunc(i int) int {
    return i
}

func first() {
    firstChannel := make(chan int)
    go func() { firstChannel <- myFunc(0) }()
    go func() { firstChannel <- myFunc(1) }()
    go func() { firstChannel <- myFunc(2) }()
    go func() { firstChannel <- myFunc(3) }()
    go func() { firstChannel <- myFunc(4) }()
    go func() { firstChannel <- myFunc(5) }()
    go func() { firstChannel <- myFunc(6) }()
    go func() { firstChannel <- myFunc(7) }()
    go func() { firstChannel <- myFunc(8) }()
    go func() { firstChannel <- myFunc(9) }()
    go func() { firstChannel <- myFunc(10) }()

    for k := 0; k < 11; k++ {
        select {
        case result := <-firstChannel:
            log.Println(result)
        }
    }
}
func second() {
    secondChannel := make(chan int)
    for j := 0; j < 11; j++ {
        go func() { secondChannel <- myFunc(j) }()
        //time.Sleep(1*time.Millisecond)
    }
    for k := 0; k < 11; k++ {
        select {
        case result := <-secondChannel:
            log.Println(result)
        }
    }
}

func main() {
    fmt.Println("First set------------------")
    first()
    time.Sleep(1 * time.Second)
    fmt.Println("Second set------------------")
    second()
}

结果:

代码语言:javascript
运行
复制
First set------------------
2009/11/10 23:00:00 0
2009/11/10 23:00:00 1
2009/11/10 23:00:00 2
2009/11/10 23:00:00 3
2009/11/10 23:00:00 4
2009/11/10 23:00:00 5
2009/11/10 23:00:00 6
2009/11/10 23:00:00 7
2009/11/10 23:00:00 8
2009/11/10 23:00:00 9
2009/11/10 23:00:00 10
Second set------------------
2009/11/10 23:00:01 11
2009/11/10 23:00:01 11
2009/11/10 23:00:01 11
2009/11/10 23:00:01 11
2009/11/10 23:00:01 11
2009/11/10 23:00:01 11
2009/11/10 23:00:01 11
2009/11/10 23:00:01 11
2009/11/10 23:00:01 11
2009/11/10 23:00:01 11
2009/11/10 23:00:01 11
EN

回答 1

Stack Overflow用户

发布于 2014-11-07 16:42:39

用循环

代码语言:javascript
运行
复制
for j := 0; j < 11; j++ {
    go func() { secondChannel <- myFunc(j) }()
    //time.Sleep(1*time.Millisecond)
}

创建一个闭包,j变量将在您的second()函数和在单独的go例程中运行的循环中创建的函数之间共享。(参见这里) --因此在引用j变量时存在一个争用条件。

在循环完成之前,go例程可能不会开始执行,然后所有的will都会看到j变量,因为它位于循环的末尾。

您可以通过让每个go例程引用一个单独的变量来解决这个问题:

代码语言:javascript
运行
复制
for j := 0; j < 11; j++ {
    arg := j
    go func() { secondChannel <- myFunc(arg) }()
    //time.Sleep(1*time.Millisecond)
}

现在,由循环中的func()创建的闭包引用了arg变量,该变量对于每个迭代都是分开的。

也可以通过将变量复制到func()的参数来传递它:

代码语言:javascript
运行
复制
for j := 0; j < 11; j++ {
    go func(arg int) { secondChannel <- myFunc(arg) }(j)
    //time.Sleep(1*time.Millisecond)
}
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26805657

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档