我试图找到一个类似的问题,但我不能,所以我在这里问:
我在递归函数中使用close(ch)
。我需要关闭通道以终止range
循环。但是,由于函数是递归的,close
会多次运行,这给了我:
恐慌:关闭封闭的通道
如果我发表评论close(ch)
声明,我会收到:
致命错误:所有goroutine都睡着了 - 死锁!
请在下面找到我的代码:
package main
import "golang.org/x/tour/tree"
import "fmt"
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
ch<-(t.Value)
if t.Left != nil { Walk(t.Left, ch) }
if t.Right != nil { Walk(t.Right, ch) }
close(ch) // => How to close a channel inside recursive function? ***
return
}
func main() {
ch := make(chan int)
go Walk(tree.New(1), ch)
for i := range ch {
fmt.Print(i, " ")
}
}
答案 0 :(得分:8)
关闭递归函数之外的通道:
func Walk(t *tree.Tree, ch chan int) {
ch<-(t.Value)
if t.Left != nil { Walk(t.Left, ch) }
if t.Right != nil { Walk(t.Right, ch) }
}
func main() {
ch := make(chan int)
go func() {
defer close(ch)
Walk(tree.New(1), ch)
}()
for i := range ch {
fmt.Print(i, " ")
}
}
答案 1 :(得分:1)
Cerise Limón的答案很好。我只想提一下,在闭包内使用read()
不是强制性的:
defer
package main
import (
"fmt"
"golang.org/x/tour/tree"
)
func Walk(t *tree.Tree, ch chan int) {
if t.Left != nil { Walk(t.Left, ch) }
ch <- t.Value
if t.Right != nil { Walk(t.Right, ch) }
}
func main() {
ch := make(chan int)
go func() {
Walk(tree.New(1), ch)
close(ch)
}()
for i := range ch {
fmt.Print(i, " ")
}
}
函数完成后,通道将关闭,并且两个动作都在单独的goroutine中执行。
如果我们使用
Walk
我们正在启动goroutine,但立即关闭当前通道中的频道。
由于我想在递归函数中关闭通道,所以最终这样做:
go Walk(tree.New(1), ch)
close(ch)
那样,递归调用将不会关闭通道,并且只允许func Walk(t *tree.Tree, ch chan int, closeAtTheEnd bool) {
if t.Left != nil {
// fmt.Println("Walk the Left of", t.Value)
Walk(t.Left, ch, false)
}
// fmt.Println("Send to the channel:", t.Value)
ch <- t.Value
if t.Right != nil {
// fmt.Println("Walk the Right of", t.Value)
Walk(t.Right, ch, false)
}
if closeAtTheEnd {
close(ch)
}
}
的第一个调用来执行此操作(树从根节点开始,并且在双向行走后关闭通道)。
Walk
答案 2 :(得分:0)
我发现这种书写方式更加简洁
class Department(models.Model):
name= models.CharField(max_length=100, unique=True)
def __unicode__(self):
return self.name[:50]
class DeviceGroup(models.Model):
name= models.CharField(max_length=100, unique=True)
def __unicode__(self):
return self.name[:50]