One-way channels

Another possibility when handling channel variables is specifying whether they are only for sending or only for receiving data. This is indicated by the <- arrow, which will precede chan if it's just for receiving, or follow it if it's just for sending:

func main() {
var a = make(chan int)
s, r := (chan<- int)(a), (<-chan int)(a)
fmt.Printf("%T - %T", s, r)
}

The full example is available at https://play.golang.org/p/ZgEPZ99PLJv.

Channels are already pointers, so casting one of them to its send-only or receive-only version will return the same channel, but will reduce the number of operations that can be performed on it. The types of channels are as follows:

When a function argument is a send/receive channel, the conversion is implicit and it is a good practice to adopt because it prevents mistakes such as closing the channel from the receiver. We can take the other example and make use of the one-way channels with some refactoring.

We can also create a function for sending values that uses a send-only channel:

func send(ch chan<- int, max int) {
for i := 0; i < max; i++ {
ch <- i
}
close(ch)
}

Do the same thing for receiving using a receive-only channel:

func receive(ch <-chan int) {
for v := range ch{
fmt.Println(v)
}
}

And then, use them with the same channel that will be automatically converted in the one-way version:

func main() {
var a = make(chan int)

go send(a, 10)

receive(a)
}

The full example is available at https://play.golang.org/p/pPuqpfnq8jJ.