Bidirectional Channels

By default, Go channels are bidirectional. A channel declared with a statement like make(chan int) can be written to and read from.

ch := make(chan int)
go func() { ch <- 42 }()
val := <-ch
fmt.Printf("%d\n", val)

Creating a bidirectional channel, writing to it and reading from it

Making Channels Send-Only or Receive-Only

Consider the following code:

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

//...

func foo(ch <-chan int) {
    // channel can be read from
}

The code creates the channel as above, but in the context of foo(), the channel is now receive-only. The same thing could be done in some other function, to make a channel send-only:

func bar(ch chan<- int) {
    // channel can be written to
}

In the context of the bar() function here, the channel can be written to, but it is invalid to read from it.

These checks are done at compile time, so we will see a compilation error if we attempt to read from the channel in a send-only context.

A Frivolous Aside

While many Go developers won’t look at it like this, a tiny fraction of readers might find something pleasing in what is actually going on here. Parameter type declarations like chan<- interface{} don’t change the variable at the point of creation, but only alter its type within the context of the function receiving the channel. The term for this is type coercion, and it is much more commonly seen in languages with a rich dynamic typing feature set than it is in statically typed languages like Go.

Summary

A picture of a chocolate Easter egg

Type coercion of channel directionality is a lovely little Easter egg in Go

This little Easter egg in Go can really help communicate clearly what a channel is for within the scope of a function. You don’t have to use send-only or receive-only type declarations with your parameters, but if you do, it will immediately be clear to the reader what the channel should be used for in this scope. You will also benefit from compile-time errors, should you make a mistake and try to read from a channel you meant to write to, or vice versa.