DeployU
Interviews / Backend Engineering / What is the difference between a buffered and an unbuffered channel in Go?

What is the difference between a buffered and an unbuffered channel in Go?

conceptual Concurrency Interactive Quiz Code Examples

The Scenario

You are a backend engineer at a fintech company. You are writing a new service that needs to communicate between two goroutines. You are not sure whether to use a buffered or an unbuffered channel.

The Challenge

Explain the difference between a buffered and an unbuffered channel in Go. What are the pros and cons of each approach, and which one would you choose for this use case?

Wrong Approach

A junior engineer might think that they are interchangeable. They might not be aware of the performance implications of choosing one over the other.

Right Approach

A senior engineer would be able to provide a detailed explanation of the differences between a buffered and an unbuffered channel. They would also be able to explain the trade-offs between each approach and would have a clear recommendation for which one to use in this use case.

Step 1: Understand the Key Differences

FeatureUnbuffered ChannelBuffered Channel
CapacityHas a capacity of zero.Has a capacity of one or more.
BlockingA sender is blocked until a receiver is ready, and a receiver is blocked until a sender is ready.A sender is blocked only if the buffer is full, and a receiver is blocked only if the buffer is empty.
Use CasesWhen you need to synchronize two goroutines.When you want to decouple the sender and the receiver.

Step 2: Choose the Right Tool for the Job

For our use case, it depends on whether we need to synchronize the two goroutines.

  • If we need to make sure that the two goroutines are synchronized, we should use an unbuffered channel.
  • If we want to decouple the two goroutines and allow them to run independently, we should use a buffered channel.

Step 3: Code Examples

Here are some code examples that show the difference between the two approaches:

Unbuffered Channel:

package main

import "fmt"

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

    go func() {
        ch <- 1
    }()

    fmt.Println(<-ch)
}

In this example, the main goroutine will be blocked until the other goroutine sends a value to the channel.

Buffered Channel:

package main

import "fmt"

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

    ch <- 1

    fmt.Println(<-ch)
}

In this example, the main goroutine will not be blocked, because the channel has a capacity of one.

Practice Question

You have a sender goroutine that produces data at a faster rate than the receiver goroutine can consume it. Which of the following would be the most appropriate?