Reputation: 20467
I am playing with channels. I have this code below which contains a for loop. I don't understand why the program seem to skip every other iteration and also why the last value is 0.
package main
import (
"fmt"
"time"
)
func send(c chan int) {
for i := 1; i < 6; i++ {
time.Sleep(time.Second)
c <- i
}
close(c)
}
func main() {
c := make(chan int)
go send(c)
for range c {
fmt.Println(<-c)
}
}
Output:
2
4
0
Upvotes: 1
Views: 1084
Reputation: 59
You should check out the golang tour first. https://tour.golang.org/concurrency/4
You use two different kind of reading in the same time:
for range c
reads from c channel once, then you read again from the channel with <-c
if you would like to write out what you sent to the channel simply use one of the followings:
for value := range c {
fmt.Println(value)
}
OR
for {
select {
case value, ok := <- c:
if !ok {
return
}
fmt.Println(value)
}
}
Because you have odd number of iterations (1..5) the last 0 appears because of the read from the closed channel (default value of type).
If you use value, ok := <-c
and the channel is closed when you read from it, the value always will be the default value and ok
will be false
.
Upvotes: 2
Reputation: 5388
Your culprit is range c
https://play.golang.org/p/yGrUhdLAQE-
You should not do range on c
instead you should use infinite for loop or case statement.
func main() {
c := make(chan int)
go send(c)
for {
d, ok:= <- c
if !ok{
break
}
fmt.Println(d)
}
}
Though if you really want to use range over c
then you should do something like this
func main() {
c := make(chan int)
go send(c)
for x := range c {
fmt.Println(x)
}
}
Upvotes: 1
Reputation: 763
because range take a value from the channel the correct code would look like this
package main
import (
"fmt"
"time"
)
func send(c chan int) {
for i := 1; i < 6; i++ {
time.Sleep(time.Second)
c <- i
}
close(c)
}
func main() {
c := make(chan int)
go send(c)
for value := range c {
fmt.Println(value)
}
}
Upvotes: 3