Golang Concurrency #3 - Channels

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 channelchanis the keyword for channelintis the type of data this channel carries
Sending (left arrow points INTO channel)
ch <- 42
chis the channel<-is the send operator42is the value going into the channelRead it as: "send 42 into ch"
Receiving (left arrow points OUT OF channel)
value := <-ch
<-chmeans "receive from ch"The arrow points away from the channel
valuegets 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.






