Channel types
When declaring variables of channel type, the most common instances are like this (T is any valid type):
var v chan T
But you may also see examples as follows :
var v <-chan T
Or:
var v chan<- T
What the hell are the differences among these 3 definitions? The distinctions are here:
(1) chan T: The channel can receive and send T type data;
(2) <-chan T: The channel is read-only, which means you can only receive T type data from this channel;
(2) chan<- T: The channel is write-only, which means you can only send T type data to this channel.
The mnemonics is correlating them with channel operations:
v := <-ch // Receive from ch, and assign value to v.
ch <- v // Send v to channel ch.
<-chan T is similar to v := <-ch, so it is a receive-only channel, and it is the same as chan<- T and ch <- v.
Restricting a channel type (read-only or write-only) can let compiler do strict checks for you. For example:
package main
func f() (<-chan int) {
ch := make(chan int)
return ch
}
func main() {
r := f()
r <- 1
}
The compilation generates following errors:
invalid operation: r <- 1 (send to receive-only type <-chan int)
Furthermore, the <- operator associates with the leftmost chan possible, i.e., chan<- chan int and chan (<-chan int) aren't equal: the previous is same as chan<- (chan int), which defines a write-only channel whose data type is a channel who can receive and send int data; while chan (<-chan int) defines a write-and-read channel whose data type is a channel who can only receive int data.
References:
Channel types;
How to understand "<-chan" in declaration?.