How to make a channel that receive multiple return values from a goroutine

后端 未结 2 703
别跟我提以往
别跟我提以往 2021-02-01 12:31

I have a function in Go that returns two values. I want to run this as a goroutine, but I can\'t figure out the syntax for creating a channel that receives two values. Could som

相关标签:
2条回答
  • 2021-02-01 13:25

    Another option would be to use an anon function like so:

    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)
    }
    

    Credit to https://gist.github.com/slav/ca2ee333c29b8f76b557c9b10b371b52

    0 讨论(0)
  • 2021-02-01 13:30

    Define a custom type with fields for both values, then create a chan of that type.

    EDIT: I've also added an example (right at the bottom) that uses multiple channels rather than a custom type. I'm not sure which is more idiomatic.

    For example:

    type Result struct {
        Field1 string
        Field2 int
    }
    

    then

    ch := make(chan Result)
    

    Example of using a channel of a custom type (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)
        }
    }
    

    Produces:

    LOREM , 5
    IPSUM , 5
    DOLOR , 5
    SIT , 3
    AMET , 4

    EDIT: Example using multiple channels instead of a custom type to produce the same output (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)
        }
    }
    
    0 讨论(0)
提交回复
热议问题