Channels in Swift

import Foundation

func main() {
    // Create a new channel using a DispatchQueue
    let queue = DispatchQueue(label: "com.example.messageQueue")
    let messages = DispatchQueue.global()

    // Send a value into the channel using a closure
    messages.async {
        queue.async {
            print("ping")
        }
    }

    // Receive the value from the channel
    queue.sync {
        // This will wait until the message is received
    }
}

main()

In Swift, we don’t have direct equivalents to Go’s channels. However, we can achieve similar functionality using Grand Central Dispatch (GCD), which is Swift’s concurrency framework.

Here’s how the code works:

  1. We create a DispatchQueue named queue to act as our channel. This queue will be used to send and receive messages.

  2. We use DispatchQueue.global() to create a background queue that will act similarly to a goroutine in Go.

  3. To send a value into the channel, we use messages.async to run a closure asynchronously. Inside this closure, we use queue.async to send our “ping” message.

  4. To receive the value from the channel, we use queue.sync. This will block until the asynchronous task completes, similar to how receiving from a channel in Go would block.

When we run this program, the “ping” message is successfully passed from one asynchronous context to another via our dispatch queue.

$ swift channels.swift
ping

By default, the sync method on DispatchQueue will block until all previously submitted tasks have completed. This property allowed us to wait at the end of our program for the “ping” message without having to use any other synchronization mechanism.

While this example demonstrates a similar concept to Go’s channels, it’s important to note that Swift’s concurrency model with GCD is quite different from Go’s. In more complex scenarios, you might want to explore Swift’s newer concurrency features like async/await for more idiomatic Swift code.