【问题标题】:Go blocking from receiving channel从接收通道阻塞
【发布时间】:2016-07-16 07:44:00
【问题描述】:

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

line1
line2
line3
line4
line5
escape1
scan done
done....

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

var lines = `
line1
line2
line3
line4
line5
line6
line7
`

func main() {
    var (
        donec  = make(chan struct{})
        stream = make(chan string, 5000)
        exitc  = make(chan struct{})
    )
    go func() {
        scanner := bufio.NewScanner(strings.NewReader(lines))
    escape1:
        for {
            for scanner.Scan() {
                select {
                case <-donec:
                    fmt.Println("escape1")
                    close(stream)
                    break escape1
                default:
                    stream <- scanner.Text()
                }
            }
        }
        close(exitc)
        fmt.Println("scan done")
        return
    }()

escape2:
    for {
        select {
        case txt, ok := <-stream:
            if !ok {
                fmt.Println("stream closed!")
            }
            fmt.Println(txt)
            if strings.Contains(txt, "line5") {
                close(donec)
                <-exitc
                break escape2
            }
        }
    }
    fmt.Println("done....")
}

认为我做的一切都是对的。有人可以帮我调试这个挂起的代码吗?

谢谢!

【问题讨论】:

    标签: go concurrency channel


    【解决方案1】:

    我认为这是因为您的 escape1 for 循环包装了 for scanner.Scan() 循环。

    当我删除外部 for 循环时,它对我来说很好:https://play.golang.org/p/NU3m3Deil7

    func main() {
        var (
            donec  = make(chan struct{})
            stream = make(chan string, 5000)
            exitc  = make(chan struct{})
        )
        go func() {
            scanner := bufio.NewScanner(strings.NewReader(lines))
        escape1:
            for scanner.Scan() {
                select {
                case <-donec:
                    fmt.Println("escape1")
                    close(stream)
                    break escape1
                default:
                    stream <- scanner.Text()
                }
            }
    
            close(exitc)
            fmt.Println("scan done")
            return
        }()
    
    escape2:
        for {
            select {
            case txt, ok := <-stream:
                if !ok {
                    fmt.Println("stream closed!")
                }
                fmt.Println(txt)
                if strings.Contains(txt, "line5") {
                    close(donec)
                    <-exitc
                    break escape2
                }
            }
        }
        fmt.Println("done....")
    }
    

    【讨论】:

      猜你喜欢
      • 2020-06-20
      • 1970-01-01
      • 2021-05-03
      • 2022-01-02
      • 1970-01-01
      • 2019-11-04
      • 2021-11-28
      • 2015-04-22
      • 2012-02-26
      相关资源
      最近更新 更多