在goroutine中将字符串写入文件。

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

write string to file in goroutine

问题

我在代码中使用了go routine,如下所示:

c := make(chan string)
work := make(chan string, 1000)
clvl := runtime.NumCPU()

for i := 0; i < clvl; i++ {
	go func(i int) {
		f, err := os.Create(fmt.Sprintf("/tmp/sample_match_%d.csv", i))
		if nil != err {
			panic(err)
		}
		defer f.Close()
		w := bufio.NewWriter(f)
		for jdId := range work {
			for _, itemId := range itemIdList {
				w.WriteString("test")
			}
			w.Flush()
			c <- fmt.Sprintf("done %s", jdId)
		}
	}(i)
}

go func() {
	for _, jdId := range jdIdList {
		work <- jdId
	}

	close(work)
}()

for resp := range c {
	fmt.Println(resp)
}

这个代码是可以的,但是我可以让所有的go routine都写入同一个文件吗?就像这样:

c := make(chan string)
work := make(chan string, 1000)
clvl := runtime.NumCPU()
f, err := os.Create("/tmp/sample_match.csv")
if nil != err {
	panic(err)
}
defer f.Close()
w := bufio.NewWriter(f)

for i := 0; i < clvl; i++ {
	go func(i int) {

		for jdId := range work {
			for _, itemId := range itemIdList {
				w.WriteString("test")
			}
			w.Flush()
			c <- fmt.Sprintf("done %s", jdId)
		}
	}(i)
}

这样是行不通的会出现错误`panic: runtime error: slice bounds out of range`

<details>
<summary>英文:</summary>

I am using go routine in code as follow:

	c := make(chan string)
	work := make(chan string, 1000)
	clvl := runtime.NumCPU()

	for i := 0; i &lt; clvl; i++ {
		go func(i int) {
			f, err := os.Create(fmt.Sprintf(&quot;/tmp/sample_match_%d.csv&quot;, i))
			if nil != err {
				panic(err)
			}
			defer f.Close()
			w := bufio.NewWriter(f)
			for jdId := range work {
				for _, itemId := range itemIdList {
					w.WriteString(&quot;test&quot;)
				}
				w.Flush()
				c &lt;- fmt.Sprintf(&quot;done %s&quot;, jdId)
			}
		}(i)
	}


	go func() {
		for _, jdId := range jdIdList {
			work &lt;- jdId
		}

		close(work)
	}()

	for resp := range c {
		fmt.Println(resp)
	}

This is ok, but can I all go routine just write to one files? just like this:

	c := make(chan string)
	work := make(chan string, 1000)
	clvl := runtime.NumCPU()
	f, err := os.Create(&quot;/tmp/sample_match_%d.csv&quot;)
	if nil != err {
		panic(err)
	}
	defer f.Close()
	w := bufio.NewWriter(f)
	
	for i := 0; i &lt; clvl; i++ {
		go func(i int) {

			for jdId := range work {
				for _, itemId := range itemIdList {
					w.WriteString(&quot;test&quot;)
				}
				w.Flush()
				c &lt;- fmt.Sprintf(&quot;done %s&quot;, jdId)
			}
		}(i)
	}

This can not work, error : `panic: runtime error: slice bounds out of range`

</details>


# 答案1
**得分**: 3

- bufio.Writer 类型不支持并发访问请使用互斥锁来保护它
- 因为短字符串在每次写入时都会被刷新所以使用 bufio.Writer 没有意义直接向文件写入并使用互斥锁进行保护)。
- 没有代码来确保 goroutine 在文件关闭或程序退出之前完成请使用 sync.WaitGroup

<details>
<summary>英文:</summary>

- The bufio.Writer type does not support concurrent access.  Protect it with a mutex.  
- Because the short strings are flushed on every write, there&#39;s no point in using a bufio.Writer.  Write to the file directly (and protect it with a mutex).
- There&#39;s no code to ensure that the goroutines complete before the file is closed or the program exits. Use a sync.WaitGroup.

</details>



huangapple
  • 本文由 发表于 2016年1月15日 14:13:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/34805302.html
匿名

发表评论

匿名网友

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

确定