Channels

A way of sending data between threads

Channels block until a message can be retrieved

This is Go’s way of thread safety

ch <- v    // Send v to channel ch.
v := <-ch  // Receive from ch, and
           // assign value to v.

func sum(vals []int, cn chan int) {
	acc := 0

	for _, val := range vals {
		acc += val
	}

	cn <- acc
}

func main() {
	vals := []int{1, 3, 5}

	cn := make(chan int)

	halfWay := len(vals) / 2
	go sum(vals[:halfWay], cn)
	go sum(vals[halfWay:], cn)

	total := <-cn + <-cn
	fmt.Printf("total: %v", total)
}

// output
// total: 9

Buffers

When a channel is filled to the buffer, all further entries will be blocked until there is room

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

Close

You can close a channel, which will then stop you from being able to add entries

You can test if the channel is closed and has no values by using the ok strat

func main() {
	cn := make(chan int, 10)

	for i := 0; i < 10; i++ {
		cn <- i
	}

	close(cn)

	if val, ok := <-cn; ok {
		fmt.Printf("you can still get things %v\n", val)
	} else {
		fmt.Println("closed and no values left")
	}
}

For range

You can create a loop that infinitely just eats off a channel, until its is closed and no entires

Note: that the output is not as expected. You will need to use the sync lib to resolve that

func eater(cn chan int) {
	for val := range cn {
		fmt.Printf("%v,", val)
	}

	fmt.Println("\nNo more values")
}

func main() {
	cn := make(chan int, 10)

	go eater(cn)

	for i := 0; i < 10; i++ {
		time.Sleep(1 * time.Second)
		cn <- i
	}

	close(cn)
}

// Output
// 0,1,2,3,4,5,6,7,8,