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

时间:2015-10-04 00:26:19

标签: unit-testing testing go channel

新手去。我使用的是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)
}

2 个答案:

答案 0 :(得分:2)

查看有关channel-axioms的文章。看起来在关闭wdCh和在closeCh频道上发送真实之间会有竞争。

因此,结果取决于pushWords返回和Accumulate之间首先安排的内容。

如果TestAccumulate先运行,在closeCh上发送为true,那么当Accumulate运行时,它会选择两个频道中的任何一个,因为它们都可以运行,因为pushWords已关闭{ {1}}。

  

来自已关闭频道的接收会立即返回零值。

在发出wdCh信号之前,closedCh将随机放置一个或多个空的&#34;&#34;地图中的文字。

如果Accumulate首先运行,那么它可能会在字图中放入许多空字符串,因为它会循环直到Accumulate运行,最后它会在TestAccumulate上发送信号。

一个简单的解决方法是移动

closeCh

close(wdCh)上发送true

。这样closeCh无法返回零值,直到您在wdCh上发出信号。此外,由于closeCh没有缓冲区大小,closeCh <- true会阻止,因此closeCh在您确保{{1}之后才会被关闭已经完成了循环。

答案 1 :(得分:-2)

我认为原因是当你关闭通道时,“选择”虽然会收到信号。

因此当你在“func pushWords”中关闭“wdCh”时,Accumulate中的循环将从“&lt; -wdCh”接收信号。 也许你应该在频道关闭后添加一些代码来测试动作!

for {
    select {
    case word, ok := <-wdCh:
        if !ok {
            fmt.Println("channel wdCh is closed!")
            continue
        }
        fmt.Printf("word = %s\n", word)
        words[word]++
    case <-closeCh:
        return
    }
}