How do I use Go routines in this example?

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

How do I use Go routines in this example?

问题

我有以下的代码片段。我创建了一个通道,最多从给定目录中获取15个文件名。我认为我可以创建多个goroutine,其中一个用于在通道上产生条目,另一个用于消费它们。消费者应该打印从通道中获取的内容。

我的程序执行时没有打印任何内容,我怀疑这是因为消费者例程正在休眠 - 难道不是为每次for循环迭代启动一个新的goroutine吗?难道最终不应该有一些从通道中打印的内容吗?

  1. func (u *uniprot) produce(n string) {
  2. u.namesInDir <- n
  3. }
  4. func (u *uniprot) consume() {
  5. fmt.Println(<-u.namesInDir)
  6. }
  7. func (u *uniprot) readFilenames(dirname string) {
  8. u.namesInDir = make(chan string, 15)
  9. dir, err := os.Open(dirname)
  10. errorCheck(err)
  11. names, err := dir.Readdirnames(0)
  12. errorCheck(err)
  13. for _, n := range names {
  14. go u.produce(n)
  15. go u.consume()
  16. }
  17. }
英文:

I have the following code snippet. I create a channel that takes 15 filenames at most from a given directory. I thought that I could create goroutines where one produces entries on a channel, and another consumes them. The consumer should print things taken from the channel.

My program executes without printing and I suspect that this is because the consumer routine is sleeping - isn't a new go routine started for each iteration of the for-loop? Shouldn't there eventually be something to print from the channel?

  1. func (u* uniprot) produce(n string) {
  2. u.namesInDir &lt;- n
  3. }
  4. func (u* uniprot) consume() {
  5. fmt.println(&lt;-u.namesInDir)
  6. }
  7. func (u* uniprot) readFilenames(dirname string) {
  8. u.namesInDir = make(chan string, 15)
  9. dir, err := os.Open(dirname)
  10. errorCheck(err)
  11. names, err := dir.Readdirnames(0)
  12. errorCheck(err)
  13. for _, n := range names {
  14. go u.produce(n)
  15. go u.consume()
  16. }
  17. }

答案1

得分: 5

你需要等待goroutine完成。

为了查看问题,在for循环的末尾加上time.Sleep

要正确修复问题,可以使用sync.WaitGroup

以下是一个可能的示例(未经测试):

  1. import "sync"
  2. func (u *uniprot) produce(n string, wg *sync.WaitGroup) {
  3. defer wg.Done()
  4. u.namesInDir <- n
  5. }
  6. func (u *uniprot) consume(wg *sync.WaitGroup) {
  7. defer wg.Done()
  8. fmt.Println(<-u.namesInDir)
  9. }
  10. func (u *uniprot) readFilenames(dirname string) {
  11. u.namesInDir = make(chan string, 15)
  12. dir, err := os.Open(dirname)
  13. errorCheck(err)
  14. names, err := dir.Readdirnames(0)
  15. errorCheck(err)
  16. wg := new(sync.WaitGroup)
  17. for _, n := range names {
  18. wg.Add(2)
  19. go u.produce(n, wg)
  20. go u.consume(wg)
  21. }
  22. wg.Wait()
  23. }
英文:

You need to wait for the go routines to finish.

To see the problem put a time.Sleep at the end of the for loop.

To fix properly use a sync.WaitGroup

Here is an example of how it might work (untested)

  1. import &quot;sync&quot;
  2. func (u *uniprot) produce(n string, wg *sync.WaitGroup) {
  3. defer wg.Done()
  4. u.namesInDir &lt;- n
  5. }
  6. func (u *uniprot) consume(wg *sync.WaitGroup) {
  7. defer wg.Done()
  8. fmt.println(&lt;-u.namesInDir)
  9. }
  10. func (u *uniprot) readFilenames(dirname string) {
  11. u.namesInDir = make(chan string, 15)
  12. dir, err := os.Open(dirname)
  13. errorCheck(err)
  14. names, err := dir.Readdirnames(0)
  15. errorCheck(err)
  16. wg := new(sync.WaitGroup)
  17. for _, n := range names {
  18. wg.Add(2)
  19. go u.produce(n, wg)
  20. go u.consume(wg)
  21. }
  22. wg.Wait()
  23. }

huangapple
  • 本文由 发表于 2013年9月29日 03:23:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/19070817.html
匿名

发表评论

匿名网友

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

确定