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)
}
1
2
$ go run example.go
hello

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

1
2
$ 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)
}