从接收通道进行阻塞

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

Go blocking from receiving channel

问题

我有以下的Go代码来等待流。预期的输出是:

  1. line1
  2. line2
  3. line3
  4. line4
  5. line5
  6. escape1
  7. scan done
  8. done....

但是在line5之后,我的代码一直挂起。

  1. var lines = `
  2. line1
  3. line2
  4. line3
  5. line4
  6. line5
  7. line6
  8. line7
  9. `
  10. func main() {
  11. var (
  12. donec = make(chan struct{})
  13. stream = make(chan string, 5000)
  14. exitc = make(chan struct{})
  15. )
  16. go func() {
  17. scanner := bufio.NewScanner(strings.NewReader(lines))
  18. escape1:
  19. for {
  20. for scanner.Scan() {
  21. select {
  22. case <-donec:
  23. fmt.Println("escape1")
  24. close(stream)
  25. break escape1
  26. default:
  27. stream <- scanner.Text()
  28. }
  29. }
  30. }
  31. close(exitc)
  32. fmt.Println("scan done")
  33. return
  34. }()
  35. escape2:
  36. for {
  37. select {
  38. case txt, ok := <-stream:
  39. if !ok {
  40. fmt.Println("stream closed!")
  41. }
  42. fmt.Println(txt)
  43. if strings.Contains(txt, "line5") {
  44. close(donec)
  45. <-exitc
  46. break escape2
  47. }
  48. }
  49. }
  50. fmt.Println("done....")
  51. }

我认为我做得没错。有人可以帮我调试这个挂起的代码吗?

谢谢!

英文:

I have the following go code to wait for streams. The expected output is:

  1. line1
  2. line2
  3. line3
  4. line4
  5. line5
  6. escape1
  7. scan done
  8. done....

But after line5, my code keeps hanging.

  1. var lines = `
  2. line1
  3. line2
  4. line3
  5. line4
  6. line5
  7. line6
  8. line7
  9. `
  10. func main() {
  11. var (
  12. donec = make(chan struct{})
  13. stream = make(chan string, 5000)
  14. exitc = make(chan struct{})
  15. )
  16. go func() {
  17. scanner := bufio.NewScanner(strings.NewReader(lines))
  18. escape1:
  19. for {
  20. for scanner.Scan() {
  21. select {
  22. case &lt;-donec:
  23. fmt.Println(&quot;escape1&quot;)
  24. close(stream)
  25. break escape1
  26. default:
  27. stream &lt;- scanner.Text()
  28. }
  29. }
  30. }
  31. close(exitc)
  32. fmt.Println(&quot;scan done&quot;)
  33. return
  34. }()
  35. escape2:
  36. for {
  37. select {
  38. case txt, ok := &lt;-stream:
  39. if !ok {
  40. fmt.Println(&quot;stream closed!&quot;)
  41. }
  42. fmt.Println(txt)
  43. if strings.Contains(txt, &quot;line5&quot;) {
  44. close(donec)
  45. &lt;-exitc
  46. break escape2
  47. }
  48. }
  49. }
  50. fmt.Println(&quot;done....&quot;)
  51. }

Think I am doing everything right. Could anybody help me debug this hanging code?

Thanks!

答案1

得分: 1

我认为问题出在你的 escape1 循环包裹了 for scanner.Scan() 循环。

当我移除外部的循环后,代码在我这里可以正常工作:https://play.golang.org/p/NU3m3Deil7

  1. func main() {
  2. var (
  3. donec = make(chan struct{})
  4. stream = make(chan string, 5000)
  5. exitc = make(chan struct{})
  6. )
  7. go func() {
  8. scanner := bufio.NewScanner(strings.NewReader(lines))
  9. escape1:
  10. for scanner.Scan() {
  11. select {
  12. case <-donec:
  13. fmt.Println("escape1")
  14. close(stream)
  15. break escape1
  16. default:
  17. stream <- scanner.Text()
  18. }
  19. }
  20. close(exitc)
  21. fmt.Println("scan done")
  22. return
  23. }()
  24. escape2:
  25. for {
  26. select {
  27. case txt, ok := <-stream:
  28. if !ok {
  29. fmt.Println("stream closed!")
  30. }
  31. fmt.Println(txt)
  32. if strings.Contains(txt, "line5") {
  33. close(donec)
  34. <-exitc
  35. break escape2
  36. }
  37. }
  38. }
  39. fmt.Println("done....")
  40. }

请注意,我只是翻译了你的代码,并没有回答你的问题。

英文:

I think it's because your escape1 for loop wraps the for scanner.Scan() loop.

When I remove that outer for loop it works fine for me: https://play.golang.org/p/NU3m3Deil7

  1. func main() {
  2. var (
  3. donec = make(chan struct{})
  4. stream = make(chan string, 5000)
  5. exitc = make(chan struct{})
  6. )
  7. go func() {
  8. scanner := bufio.NewScanner(strings.NewReader(lines))
  9. escape1:
  10. for scanner.Scan() {
  11. select {
  12. case &lt;-donec:
  13. fmt.Println(&quot;escape1&quot;)
  14. close(stream)
  15. break escape1
  16. default:
  17. stream &lt;- scanner.Text()
  18. }
  19. }
  20. close(exitc)
  21. fmt.Println(&quot;scan done&quot;)
  22. return
  23. }()
  24. escape2:
  25. for {
  26. select {
  27. case txt, ok := &lt;-stream:
  28. if !ok {
  29. fmt.Println(&quot;stream closed!&quot;)
  30. }
  31. fmt.Println(txt)
  32. if strings.Contains(txt, &quot;line5&quot;) {
  33. close(donec)
  34. &lt;-exitc
  35. break escape2
  36. }
  37. }
  38. }
  39. fmt.Println(&quot;done....&quot;)
  40. }

huangapple
  • 本文由 发表于 2016年3月29日 07:03:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/36272673.html
匿名

发表评论

匿名网友

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

确定