为具有两个返回参数的函数创建通道。

huangapple go评论86阅读模式
英文:

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() // 错误:在单值上下文中使用多值boolInt()
		chanBool, chanInt <- boolInt() // 语法错误:意外的分号或换行符,期望:=或=或逗号
	}()
}

当我尝试在单值上下文中使用它时,chanBool <- boolInt()会出现错误:在单值上下文中使用多值boolInt()

在双值上下文中:
chanBool, chanInt <- boolInt()会出现错误:语法错误:意外的分号或换行符,期望:=或=或逗号

playground

英文:

Is it posible to create channel for function boolInt without redefining it?

package main

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

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

}

When I try to use it in single value context
chanBool &lt;- boolInt() I get an error: multiple-value boolInt() in single-value context.

In 2-value context:
chanBool, chanInt &lt;- boolInt() got error: syntax error: unexpected semicolon or newline, expecting := or = or comma.

playground

答案1

得分: 7

使用两个不同的通道

您想要将值发送到两个不同的通道。将值发送到通道不是一种赋值操作,因此您不能在一步中同时发送到两个通道。

首先存储boolInt()返回的值,然后像这样将值发送到两个通道:

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{}切片作为包装,但是使用struct提供了更清晰的方式和对其字段的类型安全。

**注意2:**如果boolInt()函数本身返回一个MyStruct值,将使事情更简单和清晰:

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

在这种情况下,代码将变得非常简单:

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

另一种通道解决方案

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

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

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

输出:

Received values: false 1
英文:

Using 2 different channels

You want to send values to 2 different channels. Sending a value to a channel is not an assignment, so you can't send on both channels in one step.

First store the values returned by boolInt(), then send the values to the 2 channels like this:

go func() {
	b, i := boolInt()
	chanBool &lt;- b
	chanInt &lt;- i
}()

Testing it:

go func() {
	b, i := boolInt()
	chanBool &lt;- b
	chanInt &lt;- i
}()

fmt.Println(&quot;Received bool:&quot;, &lt;-chanBool)
fmt.Println(&quot;Received int:&quot;, &lt;-chanInt)

Output:

Received bool: false
Received int: 1

Note: you first have to receive from chanBool because you created unbuffered channels, and because in the example we first send to chanBool, that blocks until the sent value is recevied and only then proceeds to send a value to the chanInt. Attempting to receive from chanInt first would cause a deadlock (&quot;fatal error: all goroutines are asleep - deadlock!&quot;).

Solution using only one channel

If you want to send multiple values on a channel, you can create a wrapper struct for the values:

type MyStruct struct {
	b bool
	i int
}

And using it:

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

fmt.Println(&quot;Received value:&quot;, &lt;-ch)

Output:

Received value: {false 1}

Note: You could also use a []interface{} slice as a wrapper, but a struct provides a clearer way and type safety to its fields.

Note #2: It would make things easier and clearer if the boolInt() function itself would return a MyStruct value:

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

In which case code would be as simple as this:

ch := make(chan MyStruct)
go func() {
	ch &lt;- boolInt()
}()

Alternative 1 channel solution

Another option is to make the channel type interface{} so it can receive values of any type, and just send/receive multiple values on it:

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

fmt.Println(&quot;Received values:&quot;, &lt;-ch, &lt;-ch)

Output:

Received values: false 1

答案2

得分: 1

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

type BoolPlusInt struct {
    B bool
    I int
}

然后,在将其发送到通道之前,你可以创建一个该类型的值来保存这两个值。例如:

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

如果你有多个 goroutine 在通道上发送或接收数据,这种解决方案可能更可取。由于这两个值被打包在一起,你不需要担心一个地方的错误导致两个通道不同步。

你可以在这里尝试这个建议:http://play.golang.org/p/I_Apg4ciFI

英文:

If you want to send two values down a channel together, one option is to use a struct to pack both values together. For example:

type BoolPlusInt struct {
    B bool
    I int
}

You can then create a value of this type holding the two values before sending it down the channel. For instance:

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

This solution might be preferable if you have multiple goroutines sending or receiving on the channel. Since the two values are packed together you don't need to worry about bugs in one place leading to the two channels getting out of sync.

You can experiment with this suggestion here: http://play.golang.org/p/I_Apg4ciFI

huangapple
  • 本文由 发表于 2015年1月6日 16:46:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/27795036.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定