In Go I return (value, error) and check if err != nil. What does EK9 use instead?

← Error Handling and Exceptions · Ref: Q1009

EK9 has two approaches that replace Go's (value, error) pattern:

1. GUARDS (most common)
Go: result, err := doSomething(); if err != nil { handleError(err) }

EK9:

  if result <- doSomething()
    useResult(result)
  else
    handleMissing()

The guard declares 'result' AND checks if the function returned a set value. The else block handles the missing/error case.

2. RESULT TYPE (for explicit ok/error)
Go: func divide(a, b float64) (float64, error)

EK9:

  divide() as pure
    ->
      a as Float
      b as Float
    <- rtn as Result of (Float, String): Result() of (Float, String)
    if b?
      rtn: rtn.asOk(a / b)
    else
      rtn: rtn.asError("no divisor")

Result holds either an ok value, an error value, or both.

3. TRY/CATCH (for exceptions)
Go: panic/recover (rare). EK9: try/catch/finally (like Java).

The guard pattern is the closest to Go's style — short, inline, and the variable only exists if the operation succeeded.

Example

defines module qa.errorhandling.fromgoerror

  defines function

    safeDivide() as pure
      ->
        numerator as Float
        denominator as Float
      <- rtn as Float: Float()

      if denominator?
        rtn: numerator / denominator

  defines program

    FromGoErrorDemo()
      stdout <- Stdout()

      // Like Go: result, err := safeDivide(10, d); if err == nil { use(result) } else { handleError() }
      // The first denominator succeeds, the second returns unset so the else branch runs
      for denominator in [3.0, 0.0]
        if answer <- safeDivide(10.0, denominator)
          stdout.println(`Result: ${answer}`)
        else
          stdout.println("Division returned unset (like Go's err != nil)")

      // With ?: default (like Go's 'or default' pattern) - ?? would pass the unset Float through
      safeAnswer <- safeDivide(10.0, 0.0) ?: 0.0
      stdout.println(`Safe default: ${safeAnswer}`)

Common mistakes

E01073 — 'null' (and Go's 'nil') do not exist in EK9 — return the tri-state unset value Float() instead of a null literal. See ek9 -h E01073 for details.

Incorrect:

      <- rtn as Float: null

Correct:

      <- rtn as Float: Float()
Other ways to ask this
  • What is the EK9 equivalent of Go's error return pattern?
  • How do I handle errors in EK9 coming from Go?
  • Go error handling vs EK9 — what's the difference?

Coming from another language?

Go developers: your 'if err != nil' pattern becomes EK9's 'if result <- expr()' guard. The guard checks isSet, not nil (EK9 has no nil).

Keywords: result, migration, go, nil, error, guard