使用两个 return args 为 func 创建 chan

Create chan for func with two return args

是否可以在不重新定义的情况下为函数 boolInt 创建通道?

package main

func boolInt() (bool, int) {
    return false, 1
}

func main() {
    chanBool := make(chan bool)
    chanInt := make(chan int)
    go func() {
        // chanBool <- boolInt() // error: multiple-value boolInt() in single-value context
        chanBool, chanInt <- boolInt() //  syntax error: unexpected semicolon or newline, expecting := or = or comma
    }()

}

当我尝试在单值上下文中使用它时 chanBool <- boolInt() 我得到一个错误:multiple-value boolInt() in single-value context

在 2 值上下文中: chanBool, chanInt <- boolInt() 得到错误:syntax error: unexpected semicolon or newline, expecting := or = or comma.

playground

使用 2 个不同的渠道

您想将值发送到 2 个不同的通道。向通道发送值不是赋值,因此您不能一次在两个通道上发送。

首先存储由 boolInt() 编辑的值 return,然后像这样将值发送到 2 个通道:

go func() {
    b, i := boolInt()
    chanBool <- b
    chanInt <- i
}()

正在测试:

go func() {
    b, i := boolInt()
    chanBool <- b
    chanInt <- i
}()

fmt.Println("Received bool:", <-chanBool)
fmt.Println("Received int:", <-chanInt)

输出:

Received bool: false
Received int: 1

注意: 您首先必须从 chanBool 接收,因为您创建了无缓冲通道,并且因为在示例中我们首先发送到 chanBool,所以阻塞直到接收到发送的值,然后才继续将值发送到 chanInt。尝试先从 chanInt 接收会导致死锁 ("fatal error: all goroutines are asleep - deadlock!")。

仅使用一个通道的解决方案

如果您想在一个频道上发送多个值,您可以为这些值创建一个包装器 struct

type MyStruct struct {
    b bool
    i int
}

并使用它:

ch := make(chan MyStruct)
go func() {
    b, i := boolInt()
    ch <- MyStruct{b, i}
}()

fmt.Println("Received value:", <-ch)

输出:

Received value: {false 1}

注意:您也可以使用 []interface{} 切片作为包装器,但结构为其字段提供更清晰的方式和类型安全。

注意 #2: 如果 boolInt() 函数本身 return 一个 MyStruct 值,事情会变得更容易和更清楚:

func boolInt() MyStruct {
    return MyStruct{false, 1}
}

在这种情况下,代码会像这样简单:

ch := make(chan MyStruct)
go func() {
    ch <- boolInt()
}()

替代 1 通道解决方案

另一种选择是将通道类型设置为 interface{} 以便它可以接收任何类型的值,并且只是 send/receive 多个值:

ch := make(chan interface{})
go func() {
    b, i := boolInt()
    ch <- b
    ch <- i
}()

fmt.Println("Received values:", <-ch, <-ch)

输出:

Received values: false 1

如果您想将两个值一起发送到通道中,一种选择是使用结构将两个值打包在一起。例如:

type BoolPlusInt struct {
    B bool
    I int
}

然后您可以创建一个包含这两个值的此类型的值,然后再将其发送到通道。例如:

c := make(chan BoolPlusInt)
go func() {
    var v BoolPlusInt
    v.B, v.I = boolInt()
    c <- v
}()

如果您有多个 goroutines 在通道上发送或接收,则此解决方案可能更可取。由于这两个值打包在一起,您无需担心一处错误导致两个通道不同步。

您可以在此处试验此建议:http://play.golang.org/p/I_Apg4ciFI