Channels (as function parameters) can have a direction. By default a channel can both send and receive data, like func f(c chan string).

But you can define a channel to be receive-only or send-only. If you then use it in the other direction, it would show a compile-time error. This improves the type-safety of the program.

Example

Receive only

You can define a channel as func f(c <- chan string) to have a receive-only chan. If you want a send only chan, create it as func f(c chan <- string).

The program below creates a receive-only channel for the function f, func f(c <- chan string). Then the line fmt.Println(<-c) gets data from the channel.

The line c <- "hello" sets data on the channel.


package main

import "fmt"

func f(c <- chan string) {
   fmt.Println(<-c)
}

func main() {
   c := make(chan string, 1)
   c <- "hello"
   f(c)
}    
    $ go run example.go
    hello

If you then try to set data inside the function, it will tell it’s receive-only:

    $ go run example.go
    ./example.go:7:6: invalid operation: c <- "f was here" (send to receive-only type <-chan string)

Send only channel

A send only channel can set its values in a function, but cannot receive.

Change function to func f(c chan <- string). Hint: Here the only change is the position of <-.


package main

import "fmt"

func f(c chan <- string) {
   c <- "send only channel"
}

func main() {
   c := make(chan string, 1)
   f(c)
   fmt.Println(<-c)
}