Range Over Channels in Crystal

# We'll iterate over 2 values in the `queue` channel.
queue = Channel(String).new(2)
queue.send "one"
queue.send "two"
queue.close

# This `each` method iterates over each element as it's
# received from `queue`. Because we closed the
# channel above, the iteration terminates after
# receiving the 2 elements.
queue.each do |elem|
  puts elem
end

In Crystal, we use channels to achieve similar functionality to Go’s channels. Here’s how the code works:

  1. We create a buffered channel of strings with a capacity of 2 using Channel(String).new(2).

  2. We send two values, “one” and “two”, to the channel using the send method.

  3. We close the channel using the close method.

  4. We use the each method to iterate over the values in the channel. This is equivalent to the range iteration in the original example.

  5. Inside the each block, we print each element received from the channel.

When you run this program, it will output:

one
two

This example also demonstrates that it’s possible to close a non-empty channel but still have the remaining values be received. In Crystal, just like in the original example, closing the channel doesn’t immediately discard the buffered values. The each method will continue to receive values until the channel is empty, even if it has been closed.

Crystal’s syntax and channel behavior are very similar to Go’s in this case, making the translation quite straightforward. The main differences are in the method names (send instead of <- for sending, each instead of range for iterating) and the channel creation syntax.