Channels in V are very similar to channels in Go. They are the preferred way to communicate between threads.
Channels are a typed conduit through which you can send and receive values with
the channel (
Creating a channel
To create a channel of the desired type, use
chan T syntax, where
T is the type of
values that will be transferred over the channel.
When creating, you can specify the length of the buffer using the
This will create a buffered channel, which we will discuss further.
Although we will be sending values to the channels, there is no need to declare channels as
Created channels can be passed to threads as normal variables:
Sending and receiving
Values can be sent to a channel using the arrow operator
Or obtained from a channel:
By default, when you send a value to a channel, the sending channel blocks until another thread receives the value from the channel. This allows threads to be synchronized without the use of explicit locks or condition variables.
The example code sums the numbers in a slice, distributing the work between two threads. Once both threads have completed their computation, it calculates the final result.
Buffered and unbuffered channels
As already described at the beginning, when creating a channel, you can specify the length of the buffer. Such channels are called buffered.
Unlike unbuffered channels, when sending a value to a buffered channel, the sender thread is blocked only if the buffer is full.
The receiver will block when trying to read if the buffer is empty:
Try adding another value to the
ch pipe to refill the buffer and see what happens.
Closing a channel
A channel can be closed to indicate that no more values will be sent to it.
Attempting to send a value to a closed channel will cause a panic (except
The receiver can check if the channel is closed using the
If you try to read a value from a closed channel, you will get the Zero-value for the channel type. In this case, the thread will not be blocked.
Only the sender should close a channel, never the receiver.
Read all values from a channel until it's closed
Closing a channel is also useful to stop reading values from a channel using a
In the following example, we read all values from the
ch channel as long as it has values and
is not closed:
Note that we use an infinite loop until the channel is closed and the
or block is executed.
Channels aren't like files; you don't usually need to close them. Closing is only necessary when the receiver must be told there are no more values coming, such as to terminate a range loop.
select expression allows monitoring several channels at the same time without a noticeable
It consists of a list of possible cases and associated branches of statements, like a
select expression can also have a
timeout branch, which will be executed if none of the
branches is executed within the specified time.
timeout branch is specified, then
select waits for an unlimited amount of time.
In the example above, the
timeout branch will be executed in 2 seconds, because nothing will be
sent to the
ch channel and the
val := <-ch branch will not be executed.
else branch will execute immediately if none of the channels in the branches are currently
elsecannot be used together with
timeoutwithin the same
Select as an expression
select can be used as an expression of type
bool that becomes
false if all channels are
Special Channel Features
For special purposes, there are some builtin fields and methods:
try_push/pop() methods will return immediately with one of the results
.closed – dependent on whether the object has been transferred or
the reason why not.
Usage of these methods and fields in production is not recommended — algorithms based on them are often subject to race conditions.
.closed should not be used to make decisions.
or branches, error propagation or