首页 > 后端开发 > Golang > 如何使用通道在 Go 中惯用地实现递归生成器?

如何使用通道在 Go 中惯用地实现递归生成器?

Susan Sarandon
发布: 2024-12-05 09:09:13
原创
870 人浏览过

How to Idiomatically Implement Recursive Generators in Go Using Channels?

在 Go 中惯用地实现递归函数的生成器

提供的代码演示了使用通道模拟 Python 风格的递归生成器函数。

惯用的实现

按照惯例,Go 中的生成器可以使用以下方式实现goroutine 和通道如下:

  • 使用匿名函数将生成器作为 goroutine 启动: 这允许正确处理关闭通道并响应来自消费者的信号。
  • 让生成器推迟关闭通道:这可以确保通道始终关闭,即使生成器恐慌。
  • 考虑使用信号通道:这允许消费者与生成器进行通信,例如请求堕胎。

关闭通道的责任

通常,生成器函数应该负责关闭通道。这可以确保当生成器完成发送所有值时关闭通道。

修改后的代码

修改后的代码可以惯用地编写为如下:

func permutateWithChannel(channel chan<- []string, strings, prefix []string) {
    defer close(channel)
    length := len(strings)
    if length == 0 {
        channel <- prefix
        return
    }
    newStrings := make([]string, 0, length-1)
    for i, s := range strings {
        newStringsI := append(newStrings, strings[:i]...)
        newStringsI = append(newStringsI, strings[i+1:]...)
        newPrefixI := append(prefix, s)
        go permutateWithChannel(channel, newStringsI, newPrefixI)
    }
}

func PermutateWithChannel(strings []string) chan []string {
    channel := make(chan []string)
    prefix := make([]string, 0, len(strings))
    go permutateWithChannel(channel, strings, prefix)
    return channel
}
登录后复制

调用者

func main() {
    channel := lib.PermutateWithChannel(fruits)
    for myFruits := range channel {
        fmt.Println(myFruits)
        if myFruits[0] == banned {
            return
        }
    }
}
登录后复制

Goroutine 终止和恐慌

消费者关闭通道后关闭通道不会引起恐慌。事实上,尝试向关闭的通道发送值将导致关闭通道错误。

仅接收通道

将库函数限制为仅接收,惯用的方法是使用单独的通道类型来接收值和发送信号。在这种情况下,库函数将具有以下签名:

func PermutateWithChannel(strings []string) (<-chan []string, chan<- struct{})
登录后复制

以上是如何使用通道在 Go 中惯用地实现递归生成器?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板