I am learning go routines and channels,here is a basic program which i tried on the topic ,I am getting error that fatal error: all goroutines are asleep - deadlock! and I also want to know why length of my channel is zero.
package main
import (
"fmt"
)
func main() {
mychannel := make(chan int)
go takeChn(mychannel)
fmt.Println("length", len(mychannel))
for res := range mychannel {
fmt.Println("firstFunc", res, len(mychannel))
}
}
func takeChn(c chan int) {
for i := 0; i < 10; i++ {
c <- (i + 1)
}
}
The length of the channel is zero, because it is an unbuffered channel. It does not store any elements.
Your program deadlocks because the for-loop never terminates. The range over the channel will terminate when the channel is closed, but you never close the channel.
If you close the channel at the end of the goroutine, the program will run without a deadlock.
Modifying the code as per Burak Serdar's input by closing the channel
package main
import (
"fmt"
)
func main() {
mychannel := make(chan int)
go takeChn(mychannel)
fmt.Println("length", len(mychannel))
for res := range mychannel {
fmt.Println("firstFunc", res, len(mychannel))
}
}
func takeChn(c chan int) {
for i := 0; i < 10; i++ {
c <- (i + 1)
}
close(c)
}
Output:
length 0
firstFunc 1 0
firstFunc 2 0
firstFunc 3 0
firstFunc 4 0
firstFunc 5 0
firstFunc 6 0
firstFunc 7 0
firstFunc 8 0
firstFunc 9 0
firstFunc 10 0
Related
Why dose not work buffer to right on the golang?
If channel become full, it is wait. This is wrong?
I don't understand how it work.
Would you tell me how work golang channel buffer?
import (
"fmt"
"runtime"
);
func main() {
runtime.GOMAXPROCS(1);
done := make(chan bool, 2);
count := 4;
go func() {
for i := 0; i < count; i++ {
done <- true
fmt.Println("AAAAAAAA", i);
}
}()
for j := 0; j < count; j++ {
<-done
fmt.Println("BBBBBBBBBB", j);
}
}
---------------------------------------------------------------------------------
AAAAAAAAAAAAAAA 0
AAAAAAAAAAAAAAA 1
AAAAAAAAAAAAAAA 2
BBBBBBBBBB 0
BBBBBBBBBB 1
BBBBBBBBBB 2
BBBBBBBBBB 3
This is my expect
AAAAAAAAAAAAAAA 0
AAAAAAAAAAAAAAA 1
BBBBBBBBBB 0
BBBBBBBBBB 1
AAAAAAAAAAAAAAA 2
AAAAAAAAAAAAAAA 3
BBBBBBBBBB 2
BBBBBBBBBB 3
The channel buffer only fills up if Go is unable to process one item before the next arrives. In your case, there's no backlog of items as each is processed quickly and efficiently.
I wanted to understand the anatomy of channels and I've made almost the same code that You've made. I've made some small changes in your code
func main() {
runtime.GOMAXPROCS(1)
done := make(chan int, 2)
count := 4
go func() {
defer close(done)
for i := 0; i < count; i++ {
done <- i
fmt.Println("AAAAAAAA", i)
}
}()
for j := 0; j < count; j++ {
i, ok := <-done
if !ok {
break
}
fmt.Println("BBBBBBBBBB", i)
}
time.Sleep(1 * time.Millisecond)
}
Now, the output will be this
AAAAAAAA 0
AAAAAAAA 1
AAAAAAAA 2
BBBBBBBBBB 0
BBBBBBBBBB 1
BBBBBBBBBB 2
BBBBBBBBBB 3
AAAAAAAA 3
I have found an interesting information about this in the book of Concurrency in Go - by Cox-Buday, Katherine
It also bears mentioning that if a buffered channel is empty and has a
receiver, the buffer will be bypassed and the value will be passed
directly from the sender to the receiver.
According this information my understanding is, when we have a buffered channel with capacity 2:
-> main goroutine is blocked, because the channel is empty
AAAAAAAA 0 -> because, there is an active receiver this value bypassed the channel
AAAAAAAA 1 -> this value is the first value in the channel
AAAAAAAA 2 -> this value is the second value in the channel and channel is full now, so this goroutine is blocked
BBBBBBBBBB 0 -> the main goroutine can unblock now and read the "bypassed" value
-> i think the anonymous goroutine can pass the third value to channel somewhere i here
BBBBBBBBBB 1 -> the main goroutine reads the first value from the channel
BBBBBBBBBB 2 -> the main goroutine reads the second value from the channel
BBBBBBBBBB 3 -> the main goroutine reads the third value
-> the main goroutine blocked by sleep
AAAAAAAA 3 -> the anonymous goroutine can run the print statement
I'm not 100% sure this happening, but It is my observation. Unbuffered channel is also buffered channel but with 0(or 1) capacity. It is also interesting, if you try your code with 0 (unbuffered) capacity. The result will be something like this:
AAAAAAAA 0
BBBBBBBBBB 0
BBBBBBBBBB 1
AAAAAAAA 1
AAAAAAAA 2
BBBBBBBBBB 2
BBBBBBBBBB 3
AAAAAAAA 3
Finally, here is my code. I used buffer for storing the results and write it out to stdout only at the end of the main function.
func main() {
runtime.GOMAXPROCS(1)
var stdoutBuff bytes.Buffer
defer stdoutBuff.WriteTo(os.Stdout)
intStream := make(chan int, 0)
go func() {
defer close(intStream)
defer fmt.Fprintln(&stdoutBuff, "Producer done.")
for i := 0; i < 5; i++ {
fmt.Fprintf(&stdoutBuff, "Before Sending: %d\n", i)
intStream <- i
fmt.Fprintf(&stdoutBuff, "After Sending: %d\n", i)
}
}()
// for integer := range intStream {
// fmt.Fprintf(&stdoutBuff, "Received: %v\n", integer)
// }
for {
fmt.Fprintf(&stdoutBuff, "Before received.\n")
v, ok := <-intStream
if !ok {
break
}
fmt.Fprintf(&stdoutBuff, "Received: %v\n", v)
}
}
I hope it helps a little bit.
Here is my program.
package main
import "fmt"
func init() {
fmt.Println("init function")
}
func main() {
// gen number to naturals channel
naturals := gen(1, 2, 3)
// write the squars in a channel
squar := dosquar(naturals)
for p := range squar {
fmt.Println("printer shows----- ", p)
}
}
func gen(nums ...int) chan int {
naturals := make(chan int)
go func() {
for _, n := range nums {
fmt.Println("generating number ", n)
naturals <- n
fmt.Println("generated number ", n)
}
//close(naturals)
}()
return naturals
}
func dosquar(naturals chan int) chan int {
// write the squars the values
squar := make(chan int)
go func() {
for number := range naturals {
fmt.Println("recieved number ", number)
squar <- number * number
fmt.Println("sent squar of number ", number*number)
}
//close(squar)
}()
return squar
}
It gives following error.
init function
generating number 1
generated number 1
generating number 2
recieved number 1
sent squar of number 1
recieved number 2
generated number 2
generating number 3
printer shows----- 1
printer shows----- 4
sent squar of number 4
recieved number 3
sent squar of number 9
printer shows----- 9
generated number 3
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/Users/siyaram/go/src/github.com/SrmHitter9062/go-pipeline/main.go:15 +0x127
goroutine 19 [chan receive]:
I expect it to be running as channels are being ranged.That leads me to a question that do we need to close the channel every time, when we are finished with them ?
Please somebody help clarifying why program is not working as expected.
You can do whatever you want, but a range loop over a channel won't exit until the channel is closed.
I have the following excerpt from an example given in a programming course, and I am not sure why a deadlock is occurring.
package main
import (
"fmt"
)
var (
Count int = 0
nFunctions int = 2
)
var sema = make(chan int)
func increment(ch chan int, nSteps int) {
for i := 0; i < nSteps; i++ {
<- sema
cnt := Count
Count = cnt + 1
ch <- 1
sema <- 1
}
return
}
func main() {
ch := make(chan int)
sema <- 1
go increment(ch, 1000)
go increment(ch, 1000)
for i := 0; i < nFunctions*1000; i++ {
<-ch
}
fmt.Printf("Count = %d\n", Count)
}
Strangely, the deadlock does not occur when I change the statement, in the main, from sema <- 1 to
go func () {
sema <- 1
}()
Any explanations for this much appreciated. The error message is :
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
Channels block both the sender and the receiver. If you send something, you are blocked until it is received. You could reduce your code even further, all you need is a channel and then write to that channel. Note that you could also use a buffered channel, which allows writes up to the buffer length without blocking. If the buffer is full however, it does still block.
I learn buffered channels in Go and some magic is hidden from me.
I have this code
package main
import (
"fmt"
)
func write(ch chan int) {
for i := 1; i <= 5; i++ {
ch <- i
fmt.Printf("Channel's length is %d\n", len(ch))
}
close(ch)
}
func main() {
ch := make(chan int, 2)
go write(ch)
for v := range ch {
fmt.Println(v)
}
}
The output is
Channel's length is 0
Channel's length is 1
Channel's length is 2
1
2
3
4
Channel's length is 2
Channel's length is 0
5
Why is the channel's length on the first iteration in write goroutine is zero? What do I don't know?
As per the concept of GO buffer, you can push elements in channels as per defined buffer size (in your case it is 2). But at the time an element is pushed into channel, same is being read by the main GO routine which leads to a decrease in the size of channel to zero. So, if you put some time.Sleep before your read statement you will get the expected result.
`
package main
import (
"fmt"
"time"
)
func write(ch chan int) {
for i := 1; i <= 5; i++ {
ch <- i
fmt.Printf("Channel's length is %d\n", len(ch))
}
close(ch)
}
func main() {
ch := make(chan int, 2)
go write(ch)
time.Sleep(2*time.Second)
for v := range ch {
fmt.Println(v)
time.Sleep(2*time.Second)
}
}`
Output for the above code is:
Channel's length is 1
Channel's length is 2
1
Channel's length is 2
2
Channel's length is 2
3
Channel's length is 2
4
5
I'm new with golang channels and could not underestimate why does program behavior changes if I specify channel buffer size
package main
import (
"fmt"
)
func channels(in <-chan bool, out chan int) {
for {
select {
case _ = <-in:
fmt.Println("Close")
close(out)
return
default:
fmt.Println("Out")
out <- 1
break
}
}
}
func main() {
in := make(chan bool)
// in := make(chan bool, 1)
out := make(chan int)
go channels(in, out)
i := 0
// Loop:
for n := range out {
fmt.Println(n)
i += 1
if i > 10 {
fmt.Println("Send close")
in <- true // Here it is became asleep
return
}
}
fmt.Println("Done")
}
Output is:
Out
Out
1
1
Out
Out
1
1
Out
Out
1
1
Out
Out
1
1
Out
Out
1
1
Out
Out
1
Send close
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/home/user/go-lessons/3/chan_4.go:39 +0x2c3
goroutine 19 [chan send]:
main.channels(0xc820072060, 0xc8200720c0)
/home/user/go-lessons/3/chan_4.go:16 +0x241
created by main.main
/home/user/go-lessons/3/chan_4.go:27 +0x97
exit status 2
If I replace in := make(chan bool) with in := make(chan bool, 1) It works properly. Why does it happen?
This is because the main goroutine is stuck writing to in
in <- true
and the other goroutine is stuck writing to out
out <- 1
If you make the write to out a case aswell it should work:
for {
select {
case <-in:
fmt.Println("Close")
close(out)
return
case out <- 1:
fmt.Println("Out")
break
}
}