【问题标题】:How to make a channel that receive multiple return values from a goroutine如何创建一个从 goroutine 接收多个返回值的通道
【发布时间】:2013-07-24 05:27:53
【问题描述】:

我在 Go 中有一个返回两个值的函数。我想将其作为 goroutine 运行,但我无法弄清楚创建接收两个值的通道的语法。有人能指出我正确的方向吗?

【问题讨论】:

    标签: go


    【解决方案1】:

    另一种选择是使用这样的匿名函数:

    package main
    
    import "fmt"
    
    func f(c chan func() (int, string)) {
        c <- (func() (int, string) { return 0, "s" })
    }
    
    func main() {
        c := make(chan func() (int, string))
        go f(c)
        y, z := (<-c)()
        fmt.Println(y)
        fmt.Println(z)
    }
    

    感谢https://gist.github.com/slav/ca2ee333c29b8f76b557c9b10b371b52

    【讨论】:

    • 我喜欢这种创造性,但更喜欢创建自定义类型以提高可读性。 无耻的自以为是的评论>
    • 我有点迷失在@Hace 的评论和 pwaterz 的回答之间。我都喜欢
    【解决方案2】:

    定义一个包含两个值的字段的自定义类型,然后创建该类型的 chan

    编辑:我还添加了一个使用多个渠道而不是自定义类型的示例(位于底部)。我不确定哪个更惯用。

    例如:

    type Result struct {
        Field1 string
        Field2 int
    }
    

    然后

    ch := make(chan Result)
    

    使用自定义类型(Playground)频道的示例:

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    type Result struct {
        allCaps string
        length  int
    }
    
    func capsAndLen(words []string, c chan Result) {
        defer close(c)
        for _, word := range words {
            res := new(Result)
            res.allCaps = strings.ToUpper(word)
            res.length = len(word)
            c <- *res       
        }
    }
    
    func main() {
        words := []string{"lorem", "ipsum", "dolor", "sit", "amet"}
        c := make(chan Result)
        go capsAndLen(words, c)
        for res := range c {
            fmt.Println(res.allCaps, ",", res.length)
        }
    }
    

    生产:

    洛雷姆,5
    IPSUM , 5
    多洛尔 , 5
    坐 , 3
    AMET , 4

    编辑:使用多个通道而不是自定义类型来产生相同输出的示例 (Playground):

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func capsAndLen(words []string, cs chan string, ci chan int) {
        defer close(cs)
        defer close(ci)
        for _, word := range words {
            cs <- strings.ToUpper(word)
            ci <- len(word)
        }
    }
    
    func main() {
        words := []string{"lorem", "ipsum", "dolor", "sit", "amet"}
        cs := make(chan string)
        ci := make(chan int)
        go capsAndLen(words, cs, ci)
        for allCaps := range cs {
            length := <-ci
            fmt.Println(allCaps, ",", length)
        }
    }
    

    【讨论】:

    • @nick-craig-wood 感谢您的编辑,我匆忙提交。
    • 那太糟糕了;它似乎破坏了允许多个返回值的全部意义
    • 有趣的地方。能够做c := make(chan string, err) 或类似的操作并在“幕后”创建相关数据结构会很酷。也许值得一个 Go 功能请求?
    • 不要对需要匹配的值对使用多个通道。启动两个写入同一个通道的 goroutine,最终你会因为竞争条件而得到不匹配的值。
    • 简单,天才优雅的想法!我想到了一个数组,但是一个对象/结构要清晰得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-08
    • 2020-08-02
    • 1970-01-01
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    相关资源
    最近更新 更多