Different result when using for loops on channels

Hi, I’m learning channels right now. I noticed when I use for loop 3 components, the result is 1 2. But with for loop range, I got the desired result, 1 2 3 4.

package main

import (
	"fmt"
)

func main() {
	ch := make(chan int, 4)

	ch <- fetchValue(1)
	ch <- fetchValue(2)
	ch <- fetchValue(3)
	ch <- fetchValue(4)

	close(ch)

	for range len(ch) {
		result := <-ch
		fmt.Println(result) // 1 2 3 4
	}


	for i := 0; i < len(ch); i++ {
		result := <-ch
		fmt.Println(result) // 1 2
	}

}

func fetchValue(v int) int {
	return v
}

Could someone explain why that happened? A link for references would be helpful. Thanks.

In the second for loop len(ch) changes with each iteration because you are emptying the channel. So, by the time you get to 2, you already consumed two elements from the channel and now len(ch) == 2 and i == 2.

1 Like

Which line instructs it to empty the channel? Do you have an example to produce similar results or anything to improve my understanding regarding this kind of behavior? I’m totally confused about it. Thanks.

Edit
After debugging, it is correct that the channel is emptied the moment after I received it result := <-ch

Thanks for the explanation. Much appreciated.

Just for completeness, your range loop can be simplified to be:

	for result := range ch {
		fmt.Println(result) // 1 2 3 4
	}

Since the channel is closed, the loop will exit when it has finished reading all the values out of the channel.

3 Likes