使用两个返回参数为func创建chan

时间:2015-01-06 08:46:49

标签: go channel goroutine

是否可以为函数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

在双价值背景下: chanBool, chanInt <- boolInt()收到错误:syntax error: unexpected semicolon or newline, expecting := or = or comma

playground

2 个答案:

答案 0 :(得分:6)

使用2个不同的频道

您想要将值发送到2个不同的频道。向频道发送值不是分配,因此您无法在一个步骤中发送这两个频道。

首先存储boolInt()返回的值,然后将值发送到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()函数本身会返回MyStruct值,这将使事情变得更容易和更清晰:

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

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

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

替代1频道解决方案

另一种选择是制作频道类型interface{},以便它可以接收任何类型的值,并在其上发送/接收多个值:

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

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

输出:

Received values: false 1

答案 1 :(得分: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