我正在使用 channel 在 Go 中构建一个异步 Btree,但我收到错误 fatal error: all goroutines are asleep - deadlock!
我不知道为什么因为我在带有缓冲 channel 的 for 循环中从 channel 中获取值。
type Obj interface {
Compare(node Obj) int
}
type Tree struct {
Item Obj
Rigth, Left *Tree
height int16
}
func NewTree() *Tree {
return &Tree{Item: nil, Rigth: nil, Left: nil, height: 0}
}
func InOrder(t *Tree, chTree chan Obj) {
if t != nil {
InOrder(t.Left, chTree)
chTree <- t.Item
InOrder(t.Rigth, chTree)
}
}
// == testing ==
func TestInOrder(t *testing.T) {
tree := NewTree()
nums := []int{9, 7, 2, 4, 6, 10, 1, 5, 8, 3}
for i := 0; i < len(nums); i++ {
tree.Insert(ObjInt{nums[i]})
}
result := make(chan Obj, 10)
go InOrder(tree, result)
var previous Obj
for obj := range result {
fmt.Println(obj)
if previous == nil {
previous = obj
continue
}
assertTrue(previous.Compare(obj) == -1, t,
"Previous obj should be smaller than current object")
previous = obj
}
}
输出:
1
2
3
4
5
6
7
8
9
10
fatal error: all goroutines are asleep - deadlock!
最佳答案
您没有关闭 channel 。您会注意到它实际上打印正确,然后吓坏了。
在 channel 上的 range
中,如下所示:
for obj := range result {
//...
}
只有调用 close(result)
时循环才会退出。在这种情况下,由于递归的性质,它有点棘手。最后,我建议像这样包装对 InOrder
的调用:
func InOrder(t *Tree, chTree chan obj) {
inOrder(t, chTree)
close(chTree)
}
func inOrder(t *Tree, chTree chan Obj) {
if t != nil {
inOrder(t.Left, chTree)
chTree <- t.Item
inOrder(t.Rigth, chTree)
}
}
关于go - channel 僵局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23316798/