gpt4 book ai didi

go - 同时计算树叶

转载 作者:数据小太阳 更新时间:2023-10-29 03:11:04 25 4
gpt4 key购买 nike

我想使用并发模型编写一个函数,以防输入太大并且并行处理会更有效,但它永远不会结束。

假设有一个 struct 定义为:

type Tree struct {
Name string `json:"name"`
SubTrees []*Tree `json:"subTrees,omitempty"`
Leaves []string `json:"leaves"`
}

我想编写一个函数来计算整个递归结构中叶子的总数。这很容易通过递归完成:

func (tree *Tree) CountLeaves() int {
curr := len(tree.Leaves)
for _, s := range tree.SubTrees {
curr += s.CountLeaves()
}
return curr
}

这很好,但是如果结构变得太大,这将是低效的,所以我想将它重构为并发并使用 channel 。这是我对重构的尝试:

func (tree *Tree) CountLeaves() int {
var wg sync.WaitGroup
ch := make(chan int)
defer close(ch)
go count(tree, true, ch, &wg)

var total int
wg.Add(1)
go func(total *int) {
for x := range ch {
fmt.Println(x)
*total += x
}
wg.Done()
}(&total)
wg.Wait()

return total
}

func count(t *Tree, root bool, ch chan int, wg *sync.WaitGroup) {
defer wg.Done()
ch <- len(t.Leaves)
if t.SubTrees != nil {
wg.Add(len(t.SubTrees))
for _, s := range t.SubTrees {
go count(s, false, ch, wg)
}
wg.Wait()
}

if root {
ch <- -1
}
}

我目前能够通过我目前需要计算Leaves总数的 channel 收集所有数字,但该功能永远不会结束。来自根 Tree 结构的终止值 -1 永远不会通过 channel 推送或接收,我不明白为什么。

有什么想法吗?

最佳答案

我很确定您的 WaitGroup 永远不会获得足够的 wg.Done 调用:

go func(total *int) {
for x := range ch {
fmt.Println(x)
*total += x
}
wg.Done()
}(&total)

因为您永远不会关闭 ch,所以永远不会在此处调用 wg.Done。我认为如果你将它移动到循环中:

go func(total *int) {
for x := range ch {
fmt.Println(x)
*total += x
wg.Done()
}
}(&total)

这将解决问题。

编辑:

其实我觉得还有一个问题:

defer wg.Done()
ch <- len(t.Leaves)
if t.SubTrees != nil {
wg.Add(len(t.SubTrees))
for _, s := range t.SubTrees {
go count(s, false, ch, wg)
}
wg.Wait()
}

延迟的 wg.Done() 在您返回之前不会被调用,因此此 wg.Wait() 也将永远等待。这很可能是:

ch <- len(t.Leaves)
if t.SubTrees != nil {
wg.Add(len(t.SubTrees))
for _, s := range t.SubTrees {
go count(s, false, ch, wg)
}
wg.Done()
wg.Wait()
} else {
wg.Done()
}

关于go - 同时计算树叶,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51620244/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com