我对下面的GO程序有疑问,该程序使用go例程和select语句计算字母、数字、特殊字符和空格的个数
func main() {
letters := make(chan int)
digits := make(chan int)
others := make(chan int)
spaces := make(chan int)
//c := make(chan int)
//tot := 0
text := `William Butler Yeats (1865-1939) is one of the greatest of all Irish poets.
No Second Troy
Why should I blame her that she filled my days
With misery, or that she would of late
Have taught to ignorant men most violent ways,
Or hurled the little streets upon the great,
Had they but courage equal to desire?
What could have made her peaceful with a mind
That nobleness made simple as a fire,
With beauty like a tightened bow, a kind
That is not natural in an age like this,
Being high and solitary and most stern?
Why, what could she have done, being what she is?
Was there another Troy for her to burn?`
go cntLetters(text, letters)
go cntDigits(text, digits)
go cntOthers(text, others)
go cntSpaces(text, spaces)
for i := 0; i < 5; i++ {
select {
case t1 := <-letters:
fmt.Println("letter :", t1)
case t2 := <-digits:
fmt.Println("Digits :", t2)
case t3 := <-others:
fmt.Println("Others :", t3)
case t4 := <-spaces:
fmt.Println("Spaces :", t4)
}
}
//fmt.Println(tot)
}
func cntLetters(txt string, letters chan int) {
s := 0
for _, v := range txt {
if unicode.IsLetter(v) {
s++
}
}
letters <- s
}
func cntDigits(txt string, digits chan int) {
s := 0
for _, v := range txt {
if unicode.IsDigit(v) {
s++
}
}
digits <- s
}
func cntOthers(txt string, others chan int) {
s := 0
for _, v := range txt {
if !unicode.IsDigit(v) && !unicode.IsLetter(v) && !unicode.IsSpace(v) {
s++
}
}
others <- s
}
func cntSpaces(txt string, spaces chan int) {
s := 0
for _, v := range txt {
if unicode.IsSpace(v) {
s++
}
}
spaces <- s
}
字符串
运行上面的代码后,我得到了下面的输出,
Spaces : 129
Digits : 8
Others : 16
letter : 464
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [select]:
main.main()
型
根据我的理解,Select语句会等待任何通道都准备好数据。所以我创建了单独的通道来计算字母,数字,空格和字符的数量,并且无论哪个通道首先获得数据,都会由select语句执行。
问题是为什么会发生死锁,以及有什么可能的方法来消除它?
2条答案
按热度按时间olqngx591#
我想说,在这个例子中,循环是不必要的。本质上,你试图做的是并行计算,并在最后产生一个报告,对不对?
报告输出将取决于通道通信,并且不稳定(如果您有2个通道准备接收值,则将随机选择一个)。
在这个特殊的例子中,我的建议很简单:
字符串
你的循环所花费的时间比你从最慢的通道所能接收到的时间稍长。假设字母是最慢的一个,那么其他的会立即继续,你会有一个稳定的输出,而惩罚只是你会在所有的字母都完成后看到报告。
然而,有一个更强有力的论点是,你的函数在计算时不应该只接收通道来产生一个值。创建一个函数的同步接口,然后让它异步化要简单得多。例如:
型
考虑到这一点,如果你想尽快得到结果,你可以简单地使用waitgroup:
型
话虽如此,如果你想使用循环和选择语句,那么你需要确保迭代次数与读取次数相匹配。
fykwrbwg2#
我只是想提供一种替代方法,可能会对你的工作有所帮助。它使用WaitGroup,Mutex和一个单一的通道来计算你的函数。我已经包括了注解来澄清事情(希望如此)。
字符串