Skip to content

Instantly share code, notes, and snippets.

@KernelDeimos
Last active May 26, 2018 23:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KernelDeimos/384aabd36e1789efe8cbce3c17ffa390 to your computer and use it in GitHub Desktop.
Save KernelDeimos/384aabd36e1789efe8cbce3c17ffa390 to your computer and use it in GitHub Desktop.
An idea for error handling in Golang

Yet another idea for error handling in Go

Enter "trap block"

The trap block runs any time an error needs to be handled. Unlike catch in other languages, it does not divert the control flow to the end of the block. Instead, control flow is returned to the line immedately following where the error was "trapped".

Trapping an error follows a similar syntax to ignoring an error; instead of using _, use ?.

Example

func example() {
	{
		? = reportAnError()
	} trap (err error) {
		return err // only happens if err != nil
	}
}

Context

An easy way to allow some context would be to place an expression beside the ? symbol.

func example() {
	{
		data, ? "some context" = reportAnError()
	} trap (err error, message string) {
		// errors.Label() is not part of the errors
		// package, but is used here as an example.
		return errors.Label(message, err)
	}
}

An implementation could allow multiple variables for context. This would change the syntax by requiring either

  1. brackets and commas data, ? ctx1; ctx2 = reportAnError()
  2. semicolons data, ? (ctx1, ctx2) = reportAnError()

The first would make the grammar much more complicated (I think).

The second looks similar to a ternary operator in other languages, so it may cause confusion.

Variable Type

It is not necessary for the variable "trapped" to be of type error. When any interface{} that is not nil is assigned to ?, the trap bock will be invoked

Multiple values

An implementation may allow multiple variables to be assigned to ?. An intuitive behaviour would be for the trap block to be invoked if any of those values are not nil, and require the same number of variables assigned to ? as the number of variables the trap block expects.

Example

func example() {
	{
		?, ? = reportTwoErrors()
	} trap (err1, err2 error) {
		doSomethingWithErrors(err1, err2)
	}
}

Multiple error values and context

A simple implementation would only allow context after the last ? symbol.

func example() {
	{
		?, ? "context"; "more context" = reportAnError()
	} trap (err1, err2 error, message, message2 string) {
		return errors.Label(message + message2, err1, err2)
	}
}

Example

func example() {
	{
		data1, ? "buy it" := mypkg.buyIt()
		data2, err := mypkg.useIt()
		if err != nil {
			data2, ? "break it" = mypkg.breakIt()
		}
	} trap (err error, message string) {
		return errors.Label(message, err)
	}
}

Because the trap block expects (error, string), every assignment with a ? must have exactly one ?. The string would be mandatory, which successfully makes it easier to report the error with context than without.

Notes:

  • Code would not compile if any of the assignments didn't correspond to trap's signature of (error, string)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment