Golang的Go协程并发行为不如预期工作。

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

Golang go routine concurrency behaviour not working as expected

问题

以下是一个简单的Go示例。我有意省略了错误处理等内容,以使示例变得简短。我有一个简单的for循环,使用go关键字调用writeOutput函数5次,以使函数并发运行。

我期望发生的是在/tmp/目录下创建5个文件,文件内容为test。

实际发生的是没有创建任何文件。

然而,如果我移除go关键字,代码会按预期执行。我可能忽视了一些非常明显的东西。我的背景是像PHP/Ruby这样的动态类型语言,所以刚开始接触Go,无法理解为什么存在go关键字时会创建5个文件。

package main

import (
  "os"
  "math/rand"
  "strconv"
)

func main() {

  for i := 0; i < 5; i++ {
   go writeOutput()
  }

}

func writeOutput() {
  filename := strconv.Itoa(rand.Intn(10000))
  file, _ := os.Create("/tmp/" + filename)
  defer file.Close()
  file.WriteString("test")
}
英文:

Below is a simple go example. I have omitted error handling etc intentionally to make the example short. I have a simple for loop calling the writeOutput function 5 times using the go keyword to make the function run concurrently.

What I expect to happen is 5 files are created in /tmp/ with the contents of test.

What happens is that no files are created.

However if I remove the go keyword the code executes as expected. Im overlooking something super obvious. My background is dynamically typed languages like PHP/Ruby so just getting to grips with go and can't understand why 5 files are created when the go keyword exists.

package main

import (
  &quot;os&quot;
  &quot;math/rand&quot;
  &quot;strconv&quot;
)

func main() {

  for i := 0; i &lt; 5; i++ {
   go writeOutput()
  }

}

func writeOutput() {
  filename := strconv.Itoa(rand.Intn(10000))
  file, _ := os.Create(&quot;/tmp/&quot; + filename)
  defer file.Close()
  file.WriteString(&quot;test&quot;)
}

答案1

得分: 4

我使用了评论中建议的等待组(wait group)来解决了这个问题。

package main

import (
	"math/rand"
	"os"
	"strconv"
	"sync"
)

func main() {

	var wg sync.WaitGroup

	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			writeOutput()
		}()
	}
	wg.Wait()

}

func writeOutput() {
	filename := strconv.Itoa(rand.Intn(10000))
	file, _ := os.Create("/tmp/" + filename)
	defer file.Close()
	file.WriteString("test")
}

这段代码使用了等待组(wait group)来确保所有的goroutine都执行完毕后再继续执行。在主函数中,我们创建了一个等待组(wait group)并设置计数器为5。然后,使用循环创建了5个goroutine,并在每个goroutine中调用writeOutput函数。在writeOutput函数中,我们生成一个随机的文件名,创建一个文件,并将字符串"test"写入文件中。最后,我们使用defer语句关闭文件。在每个goroutine执行完毕后,我们使用wg.Done()减少计数器的值。最后,我们使用wg.Wait()等待所有的goroutine执行完毕。

英文:

I managed to solve this with a wait group as suggested in the comments.

package main

import (
	&quot;math/rand&quot;
	&quot;os&quot;
	&quot;strconv&quot;
	&quot;sync&quot;
)

func main() {

	var wg sync.WaitGroup

	for i := 0; i &lt; 5; i++ {
		wg.Add(1)
		go func() {
            defer wg.Done()
			writeOutput()
		}()
	}
	wg.Wait()

}

func writeOutput() {
	filename := strconv.Itoa(rand.Intn(10000))
	file, _ := os.Create(&quot;/tmp/&quot; + filename)
	defer file.Close()
	file.WriteString(&quot;test&quot;)
}

huangapple
  • 本文由 发表于 2016年4月2日 18:26:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/36372062.html
匿名

发表评论

匿名网友

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

确定