猿问

golang字符串通道发送/接收不一致

新去。我正在使用 1.5.1。我正在尝试根据传入频道累积一个单词列表。但是,我的输入通道 (wdCh) 在测试期间有时会得到空字符串 ("")。我很困惑。在将其累积计数添加到我的地图之前,我宁愿不对空字符串进行测试。对我来说感觉就像一个黑客。


package accumulator


import (

    "fmt"

    "github.com/stretchr/testify/assert"

    "testing"

)


var words map[string]int


func Accumulate(wdCh chan string, closeCh chan bool) {

    words = make(map[string]int)

    for {

        select {

        case word := <-wdCh:

            fmt.Printf("word = %s\n", word)

            words[word]++

        case <-closeCh:

            return

        }

    }

}


func pushWords(w []string, wdCh chan string) {

    for _, value := range w {

        fmt.Printf("sending word = %s\n", value)

        wdCh <- value

    }

    close(wdCh)

}


func TestAccumulate(t *testing.T) {

    sendWords := []string{"one", "two", "three", "two"}

    wMap := make(map[string]int)

    wMap["one"] = 1

    wMap["two"] = 2

    wMap["three"] = 1


    wdCh := make(chan string)

    closeCh := make(chan bool)


    go Accumulate(wdCh, closeCh)

    pushWords(sendWords, wdCh)


    closeCh <- true

    close(closeCh)


    assert.Equal(t, wMap, words)

}


泛舟湖上清波郎朗
浏览 261回答 2
2回答

开心每一天1111

查看这篇关于channel-axioms 的文章。看起来在关闭wdCh和在closeCh通道上发送 true之间存在竞争。因此,结果取决于在pushWords返回 和之间首先安排什么Accumulate。如果TestAccumulate首先运行,则发送 true on&nbsp;closeCh,然后在Accumulate运行时它会选择两个通道中的任何一个,因为它们都可以运行,因为pushWordsclosed&nbsp;wdCh。来自关闭通道的接收立即返回零值。直到closedCh发出信号,Accumulate会在地图中随机放置一个或多个空“”字。如果Accumulate首先运行,那么它可能会在单词映射中放入许多空字符串,因为它会循环直到TestAccumulate运行并最终在 上发送信号closeCh。一个简单的解决方法是移动close(wdCh)发送后true上closeCh。这种方式wdCh不能返回零值,直到您在closeCh.&nbsp;此外,closeCh <- true块因为closeCh没有缓冲区大小,所以wdCh在你保证Accumulate永远完成循环之前不会关闭。

慕虎7371278

我认为原因是当您关闭通道时,“选择”虽然会收到信号。因此,当您关闭“func pushWords”中的“wdCh”时,Accumulate 中的循环将从“<-wdCh”接收信号。可能是你应该添加一些代码来测试通道关闭后的动作!for {&nbsp; &nbsp; select {&nbsp; &nbsp; case word, ok := <-wdCh:&nbsp; &nbsp; &nbsp; &nbsp; if !ok {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("channel wdCh is closed!")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("word = %s\n", word)&nbsp; &nbsp; &nbsp; &nbsp; words[word]++&nbsp; &nbsp; case <-closeCh:&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }}
随时随地看视频慕课网APP

相关分类

Go
我要回答