如何创建一个从goroutine接收多个返回值的通道

Sam*_*Lee 35 go

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

Int*_*net 37

使用两个值的字段定义自定义类型,然后创建chan该类型的一个.

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

例如:

type Result struct {
    Field1 string
    Field2 int
}
Run Code Online (Sandbox Code Playgroud)

然后

ch := make(chan Result)
Run Code Online (Sandbox Code Playgroud)

使用自定义类型的频道(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)
    }
}
Run Code Online (Sandbox Code Playgroud)

生产:

LOREM,5
IPSUM,5
DOLOR,5
SIT,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)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 有趣的一点.能够执行`c:= make(chan string,err)`或类似的并且具有"幕后"创建的相关数据结构将会很酷.也许值得去Go功能请求? (5认同)
  • 这太糟糕了; 它似乎打败了允许多个返回值的整个点 (2认同)
  • 不要对需要匹配的值对使用多个通道。启动两个写入同一个通道的 goroutine,最终你会因为竞争条件而得到不匹配的值。 (2认同)

pwa*_*erz 9

另一个选择是使用像这样的anon函数:

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)
}
Run Code Online (Sandbox Code Playgroud)

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

  • 我喜欢这种创造性,但更喜欢为可读性创建自定义类型.</无耻的自以为是的评论> (6认同)
  • 我在 @Hace 的评论和 pwaterz 的回答之间有点迷失。我两个都喜欢 (2认同)