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 <- boolInt() // error: multiple-value boolInt() in single-value context
chanBool, chanInt <- boolInt() // syntax error: unexpected semicolon or newline, expecting := or = or comma
}()
}
When I try to use it in single value context
chanBool <- boolInt()
I get an error: multiple-value boolInt() in single-value context
.
In 2-value context:
chanBool, chanInt <- boolInt()
got error: syntax error: unexpected semicolon or newline, expecting := or = or comma
.
playground
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 <- b
chanInt <- i
}()
Testing it:
go func() {
b, i := boolInt()
chanBool <- b
chanInt <- i
}()
fmt.Println("Received bool:", <-chanBool)
fmt.Println("Received int:", <-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 ("fatal error: all goroutines are asleep - deadlock!"
).
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 <- MyStruct{b, i}
}()
fmt.Println("Received value:", <-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 <- boolInt()
}()
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 <- b
ch <- i
}()
fmt.Println("Received values:", <-ch, <-ch)
Output:
Received values: false 1
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 <- 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With