Length of channel is zero after adding element - go

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

Related

Channel not receiving any values if sending to many values

If I pass more than 12 for totalValues to getResults(), no values are read from channel resultCh and I get fatal error: all goroutines are asleep - deadlock!:
package main
type result struct {
index int
count int
}
func getResults(indexCh chan int, resultCh chan result, totalValues int) {
allFields := make([]int, totalValues)
for i := range allFields {
indexCh <- i
println("Sent value", i)
}
println("Sent all values")
for i := 0; i < totalValues; i++ {
value := <-resultCh
println("Received result", value.index)
allFields[value.index] = value.count
}
println("Done processing")
}
func processValue(indexCh chan int, ch chan result) {
for index := range indexCh {
println("Received value", index)
ch <- result{
index: index,
count: index * index,
}
println("Sent result", index)
}
}
func main() {
bufferDepth := 4
indexCh := make(chan int, bufferDepth)
resultCh := make(chan result, bufferDepth)
for i := 0; i < 4; i++ {
go processValue(indexCh, resultCh)
}
// Value > 12 results in goroutine asleep
getResults(indexCh, resultCh, 12)
}
The above code works by launching four goroutines using function processValue() that read values from buffered channel indexCh. Integers 0 to totalValues are inserted into indexCh by getResults(). processValue() processes the value and puts the result onto buffered channel resultCh, which is read by a getResults().
I only only observe this problem when totalValues is greater than 12. No values are read from resultCh because "Received result..." is not printed.
If I increase bufferDepth to five, the program completes successfully for totalValues > 12 and < 15.
The program also completes successfully if the buffer depth of resultCh matches totalValues.
getResults starts by writing all values to the channel. There are 4 goroutines listening, so each picks up those values, and they are blocked writing to the result channel. Channels have buffer sizes of 4. So 4 goroutines each can write a total of 4 values to result channel before blocking.
4 goroutines + 4 index channel size + 4 result channel size = 12 entries
After that, the processValue is blocked at writing to the channel, because getResults are also blocked writing to the indexCh.

issue with go routine and channel

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

Is it necessary to close a channel when sending data is finished?

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.

Understanding a Deadlock in Go

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.

Why Filter get data before prime := <- ch

https://play.golang.org/p/AyKy5odhfZw
In my sight, prime := <- ch this line is before go Filter () , every time data put into ch will be got out by prime directly.
// A concurrent prime sieve
package main
import "fmt"
// Send the sequence 2, 3, 4, ... to channel 'ch'.
func Generate(ch chan<- int) {
for i := 2; ; i++ {
ch <- i // Send 'i' to channel 'ch'.
}
}
// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func Filter(in <-chan int, out chan<- int, prime int) {
for {
i := <-in // Receive value from 'in'.
if i%prime != 0 {
out <- i // Send 'i' to 'out'.
}
}
}
// The prime sieve: Daisy-chain Filter processes.
func main() {
ch := make(chan int) // Create a new channel.
go Generate(ch) // Launch Generate goroutine.
for i := 0; i < 10; i++ {
prime := <-ch
fmt.Println(prime)
ch1 := make(chan int)
go Filter(ch, ch1, prime)
ch = ch1
}
}
Filter does not receive data first.
The way the code is written means that the variable prime will always receive the first value on the output of the filter goroutine created in the previous loop (or the generator on the first loop).
The next time around the main loop the channel variable ch will have changed to output of the next filter due to the line ch=ch1 at the end of the loop. All further integers beyond the first output by a filter will pass to the next filter in the chain.
Placing a few print statements in the filter goroutine will let you see what is happening:
func Filter(in <-chan int, out chan<- int, prime int) {
for {
i := <-in // Receive value from 'in'.
if i%prime != 0 {
fmt.Printf("Prime filter (%d): passing %d\n", prime, i)
out <- i // Send 'i' to 'out'.
} else {
fmt.Printf("Prime filter (%d): filtered %d\n", prime, i)
}
}
}
It's a little messy that the goroutines in the pipeline aren't shut down elgantly by closing the generator but that's another story :)

Resources