# Channels

A channel is a typed conduit/tube through which we send and receive values with the channel operator `<-`.

``````ch <- v        // send v to channel ch
v := <-ch      // receive from channel ch and store the value in v``````

The data flows in the direction of the arrow `<-`

We can create channels similar to creating maps and slices using the `make` function:

``ch := make(chan int)``

By default, sends and receives block until the other side is ready. This allows goroutines to synchronize without explicit locks or condition variables.

### Example

``````package main

import "fmt"

func sum(s []int, ch chan int) {
sum := 0
for _,v := range s {
sum += v
}
ch <- sum
}

func main() {
s := []int{9, 8, 7, 5, 4, 0, -9, -8}
ch := make(chan int)

go sum(s[:len(s)/2], ch)    // 4+0-9-8=-13
go sum(s[len(s)/2:], ch)    // 9+8+7+5=29
x, y := <-ch, <-ch

fmt.Println(x, y, x+y)
}``````
``-13 29 -16``

The example code sums the numbers in a slice, distributing the work between two goroutines. Once both goroutines have completed their computation, it calculates the final result.

## Buffered Channels

Channels can be buffered. Provide the buffer length as the second argument to `make` to initialize a buffered channel:

``ch := make(chan int, 100)``

Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty.

### Example

``````package main

import "fmt"

func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
// ch <- 3
fmt.Println(<-ch)
fmt.Println(<-ch)
}``````
``````1
2``````

If we overfill the buffer using the commented code on line 9, we would get: `fatal error: all goroutine are asleep - deadlock!`

Last updated