Golang : concurrency

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan int, 3) // Buffered channel with capacity 3

	// Sender goroutine
	go func() {
		for i := 0; i < 5; i++ {
			ch <- i                 // Send value to the channel
			time.Sleep(time.Second) // Simulate some work
		}
		close(ch) // Close the channel after sending all values
	}()

	// Receiver goroutine using for range
	for value := range ch {
		fmt.Println("Received:", value)
	}
}

Here, the capacity of the channel is 3, but I am sending 5 values into the channel β€˜ch’ and printing them. How come it is not causing an error?

It is not an error to send more values to the channel than its buffer size (3 in this case). What the buffer size means is that the channel will hold that many values before it blocks further input.

Thus the line

ch <- i

will receive the first 3 values as fast as possible (which is one per second given the Sleep), then the goroutine will stop at that line until the main thread gets to the range loop and starts taking values out. At that point, the channel will unblock and the goroutine can send another value.

Once it reaches close(ch) the channel will be holding at most the values 2, 3, 4 which will eventually be drained by the range.

However, given the time.Sleep, the channel will only ever have one value in it, because the main thread will take out a value before the one second is up.

The channel is working like a queue. At most 3 people can be in it, and no-one can join the queue at the back (ch <- i) until someone leaves from the front (range)

Change it to this and see the effect

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan int, 3) // Buffered channel with capacity 3

	// Sender goroutine
	go func() {
		for i := 0; i < 10; i++ {
			ch <- i // Send value to the channel
			fmt.Println("goroutine: Items in channel", len(ch))
		}
		close(ch) // Close the channel after sending all values
	}()

	time.Sleep(time.Second * 1) // Wait for channel to be full

	// Receiver goroutine using for range
	for value := range ch {
		fmt.Printf("main: Received: %d. Items left in channel %d\n", value, len(ch))
	}
}
1 Like