Different ways to pass channels as arguments in function

I always recommend that the direction is passed everywhere it is possible, e.g.

func serve(ch <-chan SomeType) { /*do stuff*/ }

func serve(ch chan<- SomeType) { /*do stuff*/ }

By including the arrow <-chan or chan<-, you are achieving three things:

  • You are making it clear that the parameter is one end of a channel.
  • You are expressing clearly which end is being supplied. chan<- is the sending (writing) end. <-chan is the receiving (reading) end.
  • You are giving more information to the compiler for checking. If the function body tries to use the wrong end of the channel, the compiler can raise an error.

These are good reasons to show the channel end whenever possible.

Your third case depicts not specifying the end of the channel. This allows both ends of the channel to be accessed, which will be correct in some cases but in other cases may lead to accidental errors.

The fourth case, passing a pointer to a channel, is quite unusual and perhaps a bit odd. If you wanted to change the channel, it would be clearer to include it as a return parameter instead.


These are different types of channels. See http://golang.org/ref/spec#Channel_types . For the pointer stuff: Uncommon, but might be useful if you want to change the channel from inside the function (never saw that in the wild).


The rule of thumb: Arrow shows if the data is going into (output) or going out of (input) channel. No arrow is general purpose channel.

chan <-          writing to channel (output channel)
<- chan          reading from channel (input channel)
chan             read from or write to channel (input/output channel)