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