I try to write a simple code in GO, in which two go routine (Send and Receive) send each other integers. I give the code below. Can anybody help me why the output of this program is [no output]. Is there any silly mistake (sorry, I am new in GO) ?
package main
func Send (in1 <-chan int, out1 chan<- int) {
i := 2
out1 <- i
print(i, "\n")
}
func Receive (in <-chan int, out chan<- int) {
i := <-in
print(i, "\n")
out <- i
}
func main() {
for i := 0; i < 10; i++ {
ch1 := make(chan int)
ch := make(chan int)
go Send (ch1 , ch)
go Receive (ch , ch1)
ch = ch1
ch1 = ch
}
}
How about this:
package main
func Send (ch chan<- int) {
for i := 0; i < 10; i++ {
print(i, " sending\n")
ch <- i
}
}
func Receive (ch <-chan int) {
for i := 0; i < 10; i++ {
print(<-ch, " received\n")
}
}
func main() {
ch := make(chan int)
go Receive(ch)
Send(ch)
}
The output of this when I run it on golang.org is:
0 sending
0 received
1 sending
2 sending
1 received
2 received
3 sending
4 sending
3 received
4 received
5 sending
6 sending
5 received
6 received
7 sending
8 sending
7 received
8 received
9 sending
I'm not sure why the 9 was never received. There should be some way to sleep the main thread until the Receive goroutine has completed. Also, it's inelegant that the receiver and the sender both know that they are going to send 10 numbers. One of the goroutines should just shut off when the other has finished its work. I'm not sure how to do that.
EDIT1:
Here is an implementation with two channels, and the go routines send ints back and forth between eachother. One is designated as the responder, who only sends and int after it receives an int. The responder simply adds two to the int he receives, and then sends it back.
package main
func Commander(commands chan int, responses chan int) {
for i := 0; i < 10; i++ {
print(i, " command\n")
commands <- i
print(<-responses, " response\n");
}
close(commands)
}
func Responder(commands chan int, responses chan int) {
for {
x, open := <-commands
if !open {
return;
}
responses <- x + 2
}
}
func main() {
commands := make(chan int)
responses := make(chan int)
go Commander(commands, responses)
Responder(commands, responses)
}
The output when I run it on golang.org is:
0 command
2 response
1 command
3 response
2 command
4 response
3 command
5 response
4 command
6 response
5 command
7 response
6 command
8 response
7 command
9 response
8 command
10 response
9 command
11 response
David Grayson's fix works, but the explanation of why 9 is not always received wouldn't fit into a comment!
When the sending goroutine sends the value on the channel, it blocks until the receiving goroutine receives it. At that point, it's unblocked. The go scheduler might return from main almost immediately before it gives the receiving goroutine a chance to print anything. If you set GOMAXPROCS to something greater than 1, this happens less frequently because the receiving goroutine won't block while the main goroutine is active.
If you want to stop main from returning until all goroutines are finished, you can return a channel from Receive(), like this:
package main
import "fmt"
func Send(ch chan<- int) {
for i := 0; i < 10; i++ {
fmt.Println(i, " sending")
ch <- i
}
close(ch)
}
func Receive(ch <-chan int) (<-chan bool) {
done := make(chan bool)
go func() {
for {
i, ok := <-ch
if !ok {
break
}
fmt.Println(i, " received")
}
done <- true
}()
return done
}
func main() {
ch := make(chan int)
d := Receive(ch)
Send(ch)
_ = <-d
}
As for why your output was empty in your original example: you make two goroutines, and thus main is totally unblocked, so it just returns and the program exits! I've definitely made this mistake too, but the runtime only joins with the main goroutine, not with ALL goroutines, like you may expect.
Related
I am trying hard to understand concurrency in Go.
package main
import "fmt"
func sendValues(myIntChannel chan int) {
for i := 0; i < 5; i++ {
myIntChannel <- i //sending value
}
}
func main() {
myIntChannel := make(chan int)
defer close(myIntChannel)
go sendValues(myIntChannel)
for value := range myIntChannel {
fmt.Println(value) //receiving value
}
}
Above code is giving below output:
0
1
2
3
4
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/Users/spikki/Desktop/GoLearning/go_channel.go:51 +0x10b
As per my understanding, defer function will execute after completion of its surrounding functions. I am not able to interpret it.
If I use for loop to receive the values from the channel its working as below.
for i := 0; i < 5; i++ {
fmt.Println(<-myIntChannel) //receiving value
}
Can anyone help me to understand this concept?
for ... range over a channel terminates only once all values have been received from the channel and the channel has been closed.
In your example you wish to close the channel in a deferred function, but that would only run when main() returns. But main() would only return if the loop would end. This is the cause of deadlock. The for loop waits for the channel to be closed, and closing the channel waits for the for loop to end.
When you use a loop to receive exactly 5 values form the channel, it works because the launched goroutines sends 5 values on it. This loop doesn't wait for the channel to be closed, so the loop can end, and so can the main() function.
That's why the sender should close the channel (not the receiver), and problem is solved immediately:
func sendValues(myIntChannel chan int) {
for i := 0; i < 5; i++ {
myIntChannel <- i //sending value
}
close(myIntChannel)
}
func main() {
myIntChannel := make(chan int)
go sendValues(myIntChannel)
for value := range myIntChannel {
fmt.Println(value) //receiving value
}
}
Output (try it on the Go Playground):
0
1
2
3
4
To explain it in a bit different terms, what your code does is:
func main() {
...
while myIntChannel is not closed {
...
}
close myIntChannel
}
Now you can see where the deadlock comes from.
While the above answer is valid, you could also try this, if you prefer using defer:
func sendValues(myIntChannel chan int) {
defer close(myIntChannel)
for i := 0; i < 5; i++ {
myIntChannel <- i //sending value
}
}
func main() {
myIntChannel := make(chan int)
go sendValues(myIntChannel)
for value := range myIntChannel {
fmt.Println(value) //receiving value
}
}
I have made a simple code example to understand the usage of pipeline, here it is.
package main
import (
"fmt"
"sync"
"time"
)
func main() {
ch1 := make(chan int, 10) // Use buffered channel so as to avoid clogging
ch2 := make(chan string, 10)
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func1(i, ch1, &wg)
go func2(ch1, ch2)
}
wg.Wait()
close(ch1)
for val := range ch2 {
fmt.Println(val)
}
}
func func1(seconds int, ch chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
time.Sleep(time.Duration(seconds) * time.Second)
fmt.Println(seconds)
ch <- seconds
}
func func2(ch1 chan int, ch2 chan string) {
for range ch1 {
ch2 <- "hello"
}
close(ch2)
}
Now, the problem is I don't get consistent output ( I understand it's some concurrency issue, which I haven't fully understood ).
Output
> go run pipeline-loop.go
0
1
2
hello
hello
> go run pipeline-loop.go
0
1
2
hello
hello
hello
> go run pipeline-loop.go
0
1
2
hello
hello
> go run pipeline-loop.go
0
1
2
hello
hello
> go run pipeline-loop.go
0
1
2
hello
hello
panic: close of closed channel
goroutine 6 [running]:
main.func2(0xc00006c000, 0xc000056180)
/home/projects/go-tuts/pipeline-loop.go:36 +0x72
created by main.main
/home/projects/go-tuts/pipeline-loop.go:16 +0x10f
exit status 2
Another guy changed the code ( and it was working ) and put func2 outside the loop but I want func2 for each iteration of the func1.
Problem
So, I want to understand as to where should the WaitGroup and close(ch) be used ?
Thanks.
Temporarya
( A golang noobie )
Update
Based on a user's answer, I changed the code, now I get output as expected ( but not the solution to this question ) but still there's a deadlock.
https://play.golang.org/p/O_rp_FLvNh8
package main
import (
"fmt"
"sync"
"time"
)
func main() {
ch1 := make(chan int, 10) // Use buffered channel so as to avoid clogging
ch2 := make(chan string, 10)
var wg1 sync.WaitGroup
// var wg2 sync.WaitGroup
for i := 0; i < 3; i++ {
wg1.Add(1)
go func1(i, ch1)
go func2(ch1, ch2, &wg1)
}
for val := range ch2 {
fmt.Println(val)
}
wg1.Wait()
close(ch1)
close(ch2)
}
// func func1(seconds int, ch chan<- int, wg *sync.WaitGroup) {
func func1(seconds int, ch chan<- int) {
// defer wg.Done()
time.Sleep(time.Duration(seconds) * time.Second)
fmt.Println(seconds)
ch <- seconds
}
func func2(ch1 chan int, ch2 chan string, wg *sync.WaitGroup) {
defer wg.Done()
for range ch1 {
ch2 <- "hello"
}
}
There are multiple problems in your code.
In the loop, you are spawning multiple (3) goroutines that runs func2, and in func2, you send data to ch2 and call close(ch2). This is a problem. It can happen that when one goroutine is seding data to ch2, the other has closed that channel, which causes:
panic: close of closed channel
goroutine 6 [running]:
main.func2(0xc00006c000, 0xc000056180)
/home/projects/go-tuts/pipeline-loop.go:36 +0x72
created by main.main
/home/projects/go-tuts/pipeline-loop.go:16 +0x10f
exit status 2
In general, you don't need close a chanel multiple times - you only need to shut them once they are all finished. You need another WaitGroup for this; you need to pass both functions a WaitGroup.
Further reading: https://blog.golang.org/pipelines
UPDATE:
Personally I use a pattern for "works" that produce data into a same channel and the channel needs to be closed after all works are done:
for something {
wg.Add(1)
go func(i int) {
work(ch)
wg.Done()
}
}
go func() {
wg.Wait()
close()
}()
I think it is a good idea that keeps the API clean from WorkGroup as WorkGroup is about how you sync the work instead of how the work is done.
I have changed your code into this pattern: https://play.golang.org/p/vdCNsxWhgyQ
I suspect you only want one channel to read from ch1 and write to ch2. There is not much point in creating 3 go-routines to do the same thing (and you also end up closing the same channel mutliple time which causes a panic as leaf bebop pointed out)
func main() {
ch1 := make(chan int, 10) // Use buffered channel so as to avoid clogging
ch2 := make(chan string, 10)
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func1(i, ch1, &wg)
}
go func2(ch1, ch2)
wg.Wait()
close(ch1)
for val := range ch2 {
fmt.Println(val)
}
}
go version go1.11.4 darwin/amd64
A new channel and goroutine were created, and the content of the old channel was transferred to the new channel through goroutine. It should not block, but after testing, it was found to be blocked.
thanks.
type waiter struct {
ch1 chan struct{}
ch2 <-chan time.Time
limit int
count int
}
func (w *waiter) recv1Block() chan struct{} {
ch := make(chan struct{})
go func() {
for m := range w.ch1 {
ch <- m
}
}()
return ch
}
func (w *waiter) runBlock(wg *sync.WaitGroup) {
defer wg.Done()
i := 0
for i < w.limit {
select {
case <-w.recv1Block(): **// why block here?**
i++
case <-w.recv2():
}
}
w.count = i
}
why recv1Block will be block.
Every time you call recv1Block(), it creates a new channel and launches a background goroutine that tries to read all of the data from it. Since you're calling it in a loop, you will have many things all trying to consume the data from the channel; since the channel never closes, all of the goroutines will run forever.
As an exercise, you might try changing your code to pass around a chan int instead of a chan struct{}, and write a series of sequential numbers, and print them out as they're ultimately received. A sequence like this is valid:
run on goroutine #1 calls recv1Block().
recv1Block() on GR#1 spawns GR#2, and returns channel#2.
run on GR#1 blocks receiving on channel#2.
recv1Block() on GR#2 reads 0 from w.c1.
recv1Block() on GR#2 writes 0 to channel#2 (where run on GR#1 is ready to read).
recv1Block() on GR#2 reads 1 from w.c1.
recv1Block() on GR#2 wants to write 0 to channel#2 but blocks.
run on GR#1 wakes up, and receives the 0.
run on GR#1 calls recv1Block().
recv1Block() on GR#1 spawns GR#3, and returns channel #3.
recv1Block() on GR#3 reads 2 from w.c1.
...
Notice that the value 1 in this sequence will never be written anywhere, and in fact there is nothing left that could read it.
The easy solution here is to not call the channel-creating function in a loop:
func (w *waiter) runBlock(wg *sync.WaitGroup) {
defer wg.Done()
ch1 := w.recv1Block()
ch2 := w.recv2()
for {
select {
case _, ok := <-ch1:
if !ok {
return
}
w.count++
case <-ch2:
}
}
It's also standard practice to close channels when you're done with them. This will terminate a for ... range ch loop, and it will appear as readable to a select statement. In your top-level generator function:
for i := 0; i < w.limit; i++ {
w.ch1 <- struct{}{}
}
close(w.ch1)
And in your "copy the channel" function:
func (w *waiter) recv1Block() chan struct{} {
ch := make(chan struct{})
go func() {
for m := range w.ch1 {
ch <- m
}
close(ch)
}()
return ch
}
This also means that you don't need to run the main loop by "dead reckoning", expecting it to produce exactly 100 items then stop; you can stop whenever its channel exits. The consumer loop I show above does this.
I want to send a value in a channel to go routines from main function. What happens is which go routine will receive the value from the channel first.
package main
import (
"fmt"
"math/rand"
//"runtime"
"strconv"
"time"
)
func main() {
var ch chan int
ch = make(chan int)
ch <- 1
receive(ch)
}
func receive(ch chan int){
for i := 0; i < 4; i++ {
// Create some threads
go func(i int) {
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
fmt.Println(<-ch)
}(i)
}
}
My current implementation is giving an error.
fatal error: all goroutines are asleep - deadlock!
How can I know that which go routine will receive the value from the channel first. And what happens to other go routine If those will run or throw an error since there is no channel to receive the value. As it is already received by one of them.
If a create a buffered channel my code works. So I don't get it what has happened behind the scene which is making it work when creating a buffered channel like below:
func main() {
var ch chan int
ch = make(chan int, 10)
ch <- 1
receive(ch)
}
If we look at below code. I can see that we can send values through channels directly there is no need of creating a go routine to send a value thorugh a channel to another go routines.
package main
import "fmt"
func main() {
// We'll iterate over 2 values in the `queue` channel.
queue := make(chan string, 2)
queue <- "one"
queue <- "two"
close(queue)
for elem := range queue {
fmt.Println(elem)
}
}
Then what is wrong with my code. Why is it creating a deadlock.
If all you need is to start several workers and send a task to any of them, then you'd better run workers before sending a value to a channel, because as #mkopriva said above, writing to a channel is a blocking operation. You always have to have a consumer, or the execution will freeze.
func main() {
var ch chan int
ch = make(chan int)
receive(ch)
ch <- 1
}
func receive(ch chan int) {
for i := 0; i < 4; i++ {
// Create some threads
go func(i int) {
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
fmt.Printf("Worker no %d is processing the value %d\n", i, <-ch)
}(i)
}
}
Short answer for the question "Which go routine will receive it?" - Whatever. :) Any of them, you can't say for sure.
However I have no idea what is time.Sleep(...) for there, kept it as is.
An unbuffered channel (without a length) blocks until the value has been received. This means the program that wrote to the channel will stop after writing to the channel until it has been read from. If that happens in the main thread, before your call to receive, it causes a deadlock.
There are two more issues: you need to use a WaitGroup to pause the completion until finished, and a channel behaves like a concurrent queue. In particular, it has push and pop operations, which are both performed using <-. For example:
//Push to channel, channel contains 1 unless other things were there
c <- 1
//Pop from channel, channel is empty
x := <-c
Here is a working example:
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func main() {
var ch chan int
ch = make(chan int)
go func() {
ch <- 1
ch <- 1
ch <- 1
ch <- 1
}()
receive(ch)
}
func receive(ch chan int) {
wg := &sync.WaitGroup{}
for i := 0; i < 4; i++ {
// Create some threads
wg.Add(1)
go func(i int) {
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
fmt.Println(<-ch)
wg.Done()
}(i)
}
wg.Wait()
fmt.Println("done waiting")
}
Playground Link
As you can see the WaitGroup is quite simple as well. You declare it at a higher scope. It's essentially a fancy counter, with three primary methods. When you call wg.Add(1) the counter is increased, when you call wg.Done() the counter is decreased, and when you call wg.Wait(), the execution is halted until the counter reaches 0.
Is it possible in go:
Suppose, I have 3 concurrent routines which can send integers to each other. Now, suppose both concurrent routine 2 & 3 sends an integer to concurrent routine 1. Is it possible in go that routine 1 takes both two values and process it farther ? To make it clear, I have following code:
package main
import "rand"
func Routine1(command12 chan int, response12 chan int, command13 chan int, response13 chan int ) {
for i := 0; i < 10; i++ {
i := rand.Intn(100)
if i%2 == 0 {
command12 <- i
}
if i%2 != 0 {
command13 <- i
}
print(<-response13, " 1st\n");
}
close(command12)
}
func Routine2(command12 chan int, response12 chan int, command23 chan int, response23 chan int) {
for i := 0; ; i++ {
x, open := <-command12
if !open {
return;
}
print(x , " 2nd\n");
y := rand.Intn(100)
if i%2 == 0 {
command12 <- y
}
if i%2 != 0 {
command23 <- y
}
}
}
func Routine3(command13 chan int, response13 chan int, command23 chan int, response23 chan int) {
for i := 0; ; i++ {
x, open := <-command13
if !open {
return;
}
print(x , " 3nd\n");
y := rand.Intn(100)
response23 <- y
}
}
func main() {
command12 := make(chan int)
response12 := make(chan int)
command13 := make(chan int)
response13 := make(chan int)
command23 := make(chan int)
response23 := make(chan int)
go Routine1(command12, response12,command13, response13 )
Routine2(command12, response12,command23, response23)
Routine3(command13, response13,command23, response23 )
}
Here, in this example routine 1 can send an int to routine 2 or 3. I assume it is routine 3. Now suppose, routine 3 also send an int to routine 2. Is it possible for routine 2 to take those two values and process further (dynamic concurrent routines)? Can any body help to modify this program accordingly.
I hate abstract examples, anyway I will do my best to answer your question.
Is it possible in go that routine 1 takes both two values and process it farther?
What do you want to archive? Inside routine1 you can either do:
// Read exactly one command from routine2 as well as exactly
// one command from routine3
cmd1 := <-command12
cmd2 := <-command13
// Process the pair of the two commands here
OR
// Process a single command only, which was either sent by routine2
// or by routine3. If there are commands available on both channels
// (command12 and command13) the select statement chooses a branch
// fairly.
select {
case cmd1 := <-command12:
// process command from routine 2
case cmd2 := <-command13
// process command from routine 3
}
I hope that will answer your question. Also note that Go channels support multiple-writers (as well as mutliple readers) by default. So, it might be enough to use exactly one input channel per goroutine. For example, routine1 might only read commands from a channel called command1, but both routine2 and routine3 might use the same command1 channel to send messages to routine1.
Another common idiom in Go is to pass a reply channel as part of the message. For example:
type Command struct {
Cmd string
Reply chan-> int
}
func routine2() {
reply := make(chan int)
command1 <- Command{"doSomething", reply}
status := <-reply
}
func routine1() {
cmd <- command1;
// process cmd.Cmd
cmd.Reply <- 200 // SUCCESS (status code)
}
Depending on your actual problem, this might simplify your program drastically :)
It's not possible in GO, I mean creating concurrent channels.