Custom Errors in Swift

import Foundation

// A custom error type usually has the suffix "Error".
struct ArgError: Error {
    let arg: Int
    let message: String
}

// Adding this localizedDescription property makes ArgError
// conform to the Error protocol.
extension ArgError: LocalizedError {
    var errorDescription: String? {
        return "\(arg) - \(message)"
    }
}

func f(_ arg: Int) throws -> Int {
    if arg == 42 {
        // Throw our custom error.
        throw ArgError(arg: arg, message: "can't work with it")
    }
    return arg + 3
}

func main() {
    do {
        let _ = try f(42)
    } catch {
        // `as?` is Swift's equivalent to Go's `errors.As`.
        // It checks if the error can be cast to a specific type.
        if let ae = error as? ArgError {
            print(ae.arg)
            print(ae.message)
        } else {
            print("err doesn't match ArgError")
        }
    }
}

main()

This Swift code demonstrates how to create and use custom errors. Here’s a breakdown of the key elements:

  1. We define a custom error type ArgError that conforms to the Error protocol.

  2. We extend ArgError to conform to LocalizedError, providing a custom error description.

  3. The f function can throw our custom error.

  4. In the main function, we use a do-catch block to handle potential errors.

  5. We use Swift’s as? operator to check if the caught error is of type ArgError. This is similar to Go’s errors.As function.

To run this program, you would save it as a .swift file and use the Swift compiler:

$ swift custom-errors.swift
42
can't work with it

This example shows how Swift handles custom errors, which is conceptually similar to Go but with syntax and patterns that are idiomatic to Swift.