Skip to main content

Command Palette

Search for a command to run...

Golang Concurrency #3 - Channels

Published
3 min read
Golang Concurrency #3 - Channels
T

Just a guy who loves to write code and watch anime.

Basic Channels

Channels are Go's way for goroutines to communicate with each other. Think of them as pipes that connect goroutines.

Creating channels

ch := make(chan int)        // Channel that carries integers
ch := make(chan string)     // Channel that carries strings

Sending and receiving

ch <- 42        // Send 42 into the channel
value := <-ch   // Receive from the channel

Basic example

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

    go func() {
        ch <- "Hello from goroutine"  // Send
    }()

    message := <-ch  // Receive
    fmt.Println(message)
}

Key insight

Channels are synchronous by default. When you send, the sender waits until someone receives. When you receive, the receiver waits until someone sends.

This blocks forever

ch := make(chan int)
ch <- 42  // No one is receiving, so this blocks forever

This also blocks forever

ch := make(chan int)
value := <-ch  // No one is sending, so this blocks forever

Channels solve the goroutine communication problem

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

    go func() {
        // Do some work
        answer := 42
        result <- answer  // Send result back
    }()

    fmt.Println(<-result)  // Wait for and print result
}

Go's motto

"Don't communicate by sharing memory; share memory by communicating."

Channels are the "communicating" part - they let goroutines pass data safely without shared variables.

Channel Syntax Breakdown

Creating

ch := make(chan int)
  • make() creates the channel

  • chan is the keyword for channel

  • int is the type of data this channel carries

Sending (left arrow points INTO channel)

ch <- 42
  • ch is the channel

  • <- is the send operator

  • 42 is the value going into the channel

  • Read it as: "send 42 into ch"

Receiving (left arrow points OUT OF channel)

value := <-ch
  • <-ch means "receive from ch"

  • The arrow points away from the channel

  • value gets whatever comes out

Memory trick

The arrow shows direction of data flow.


Go's Motto Explained

"Don't communicate by sharing memory; share memory by communicating."

Traditional way (sharing memory)

var counter int  // Shared variable
var mutex sync.Mutex

// Goroutine 1
mutex.Lock()
counter++
mutex.Unlock()

// Goroutine 2
mutex.Lock()
counter++
mutex.Unlock()

Both goroutines access the same counter variable. They "communicate" by both touching the same memory location.

Go's way (communicating)

ch := make(chan int)

// Goroutine 1
ch <- 1  // Send "increment by 1"

// Goroutine 2
ch <- 1  // Send "increment by 1"

// Counter goroutine
counter := 0
counter += <-ch  // Receive increment
counter += <-ch  // Receive increment

Instead of sharing the counter variable, goroutines send messages through channels.

The difference

  • Sharing memory = multiple goroutines touching the same variable

  • Communicating = goroutines sending data through channels

Channels eliminate the need for locks and make concurrent code safer.