Channels Buffered vs Unbuffered, defers
Channels in Go are a powerful feature used for communication between goroutines. They allow you to send and receive values, making it easy to synchronize data between concurrently running functions. Channels help to ensure that data is safely shared between goroutines and avoid race conditions.
Unbuffered Channels
- Making a new channel
ch := make(chan int)
- Call a new goroutine
go func(){ ch <- 4}()
- Receive the value from the channel in the main thread
value := <- ch
- Print the value
package main
func main() { ch := make(chan int)
go func() { ch <- 5 }()
value := <-ch println(value)}
By default sends and receives block until both the sender and receiver are ready
Channel Buffering
- A buffered channel has a specified capacity. It allows sending multiple values to the channel before it blocks.
- Sending to a buffered channel only blocks when the buffer is full, and receiving blocks when the buffer is empty.
package main
import ( "fmt" "time")
func main() { ch := make(chan int, 5)
go func() { for i := range 10 { fmt.Println("sent data ", i) ch <- i } }()
time.Sleep(time.Second * 5) println(<-ch)}
Looping over channels using range
You can also loop over channels
package main
import ( "fmt" "time")
func main() { ch := make(chan int, 5)
go func() { for i := range 10 { fmt.Println("sent data ", i) ch <- i } }()
time.Sleep(time.Second * 5) for value := range ch { println(value) }}
Closing channels, Defer
Closing a channel indicates that no more values will be sent on it.
In Go, defer
is a keyword used to schedule a function call to be executed after the surrounding function completes. It’s often used for purposes like resource cleanup, such as closing files, releasing locks, or handling other cleanup tasks, ensuring that these actions are performed regardless of how the function exits (whether it completes normally or due to a panic).
We should close the channel after the go routine dies
package main
import ( "fmt" "time")
func main() { ch := make(chan int, 5)
go func() { defer close(ch) for i := range 10 { fmt.Println("sent data ", i) ch <- i } }()
time.Sleep(time.Second * 5) for value := range ch { println(value) }}
Reading from a closed channel succeeds immediately, returning the zero value of the underlying type. The optional second return value is true
if the value received was delivered by a successful send operation to the channel, or false
if it was a zero value generated because the channel is closed and empty.
value, ok := <-chprintln(ok)