Working with Channels in Go

11.29.2021

Intro

Channels allow you to shared data between goroutines. When executing multiple concurrent tasks, you often want to send and receive data from these tasks. Channels allow you to do this. In this Article, we will learn how to use Channels in Go.

Channel Basics

There are two type of channels, Unbuffered and buffered. Unbuffered channels are used for synchronous communication and buffered is used for asynchronous communication.

To create an unbuffered channel, we use the make function like so.

unbufchannel := make(chan int)

In a similar way, we can create a buffered channel. However, we must specify the size.

buffchannel := make(chan int, 10)

We can then assign values to our channel using he <- operator.

buffchannel <- 10

Finally, we can read values from a channel using the following.

result := <-buffchannel
fmt.Println(result) // 10

Channel Example

Let's say we had a large list of numbers to compute. We can use goroutines and channels to split this sum and execute it concurrently.

We first create a sum function that takes in an array of values and a channel. The function will sum the array and add the result to the channel.

func sum(data []int, result chan int) {
	sum := 0
	for _, value := range data {
		sum += value
	}
	result <- sum
}

Then, in our main function, we will create a channel, split the array, and send the split to each goroutine. We can then retrieve the results.

func main() {
	s := []int{1, 2, 3, 4, 5, 6}

	c := make(chan int)

	// split the sum operations
	go sum(s[:len(s)/2], c)
	go sum(s[len(s)/2:], c)

	// Get the results
	res1 := <-c
	res2 := <-c

	fmt.Println(res1, res2, res1 + res2)
}

The Full Example

Here is the full example code. You can run this by copying the contents into a file called main.go and then running go run main.go.

package main

import "fmt"

func sum(data []int, result chan int) {
	sum := 0
	for _, value := range data {
		sum += value
	}
	result <- sum
}

func main() {
	s := []int{1, 2, 3, 4, 5, 6}

	c := make(chan int)

	// split the sum operations
	go sum(s[:len(s)/2], c)
	go sum(s[len(s)/2:], c)

	// Get the results
	res1 := <-c
	res2 := <-c

	fmt.Println(res1, res2, res1+res2)
}