Go Language Error Handling: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
Line 24: Line 24:


=TO DEPLETE=
=TO DEPLETE=
<font color=darkkhaki>
==External==
* Go Specification - Handling panics https://golang.org/ref/spec#Handling_panics
==Overview==
Error are not types, they are interfaces.
==The <tt>error</tt> Type==
Go has a built-in <tt>error</tt> type. It is an interface. Its definition can be found in <tt>$GO_HOME/src/builtin/builtin.go</tt>. According to the documentation: the error built-in interface type is the conventional interface for representing an error condition, with the nil value representing no error.
===The "errors" Package===
* https://golang.org/pkg/errors
====Creating Custom <tt>error</tt> Instances====
=====<tt>errors.New()</tt>=====
Custom errors can be created by using the <tt>New()</tt> function in the "errors" package. Returns an <tt>error</tt> pointer:
<pre>
import "errors"
...
errPtr := errors.New("some text")
</pre>
=====<tt>fmt.Errorf()</tt>=====
The function <tt>[[Go_Package_fmt#fmt.Errorf.28.29|fmt.Errorf()]]</tt> also creates custom error instances.
==Exceptions==
Exceptions (in the Java sense) are not available in Go.
An alternative mechanism can be implemented by function returning multiple values, out of which one is an error indicator.
<font color=red><tt>panic</tt></font>
===<tt>defer</tt> and <tt>finally</tt>===
<tt>defer</tt> puts the function on the stack.
==Panics==
A ''panic'' generally indicates a programmer error (attempting to access an array index out of bounds, writing an uninitialized map, etc.) Panics can also be synthetically triggered with:
<pre>
panic(message)
</pre>
The panic can be caught on the stack outside the function that caused the panic, by executing <tt>recover()</tt>.  Recover can be called in any upper function on the stack, or even if the function that triggers the panic, if the invocation is made with <tt>[[Go Concepts - Functions#defer|defer]]</tt>.
The <tt>recover()</tt> built-in function allows a program to manage behavior of a panicking goroutine. Executing a call to recover inside a deferred function (but not any function called by it) stops the panicking sequence by restoring normal execution and retrieves the error value passed to the call of panic. If recover is called outside the deferred function it will not stop a panicking sequence. In this case, or when the goroutine is not panicking, or if the argument supplied to panic was nil, recover returns <tt>nil</tt>. Thus the return value from recover reports whether the goroutine is panicking.
==Error Handling Idioms==
The fact that Go function can return multiple value may be used in implementing a mechanism where a function returns the "good" value and an error value, instead of an exception. If an error occurs (the error instance is not <tt>nil</tt>), you should never trust the other values being returned by the function, they should always be ignored.
This is an idiomatic way of handling errors returned by functions. For a callee function A and a calling function B:
<pre>
// the "callee"
func A(...) (<business-result-type>, error) {
    var result <business-result-type>
    // processing ...
    // some error occurs
    return <zero-value-for-type>, errors.New("dang")
    // all good, make sure to return all values, including a nil error
    return result, nil
}
// the calling function
func B(...) (<business-result-type>, error) {
    result, err := A(...)
    if err != nil {
        return <zero-value-for-type>, err
    }
    // process the callee's returned result ...
    // all good, make sure to return all values, including a nil error
    return result, nil
}
</pre>
The fact that functions return error values can be used in conjunction with the special <tt>if</tt> syntax:
<pre>
if value, error := f(); err {
  // handle err
}
else {
  // handle success
}
</pre>
More about multiple return values can be found here:
<blockquote style="background-color: #f9f9f9; border: solid thin lightgrey;">
:[[Go_Concepts_-_Functions#Multiple_Return_Values|Multiple Return Values]]
</blockquote>


<font color=darkkhaki>These are documents produced by the previous attempt. Process, merge into this document, and deplete:
[[Go Concepts - Error Handling]]
</font>
</font>

Revision as of 22:32, 30 August 2023

Internal

Overview

A common error generation pattern in Go is that function return an error instance as the second return value.

The returned error instance is implements the error interface:

type error interface {
  Error() string
}

The error interface is a pre-declared type identifier.

Organizatorium

Create an error:

errors.New("at least three arguments are required")

TO DEPLETE

External

Overview

Error are not types, they are interfaces.

The error Type

Go has a built-in error type. It is an interface. Its definition can be found in $GO_HOME/src/builtin/builtin.go. According to the documentation: the error built-in interface type is the conventional interface for representing an error condition, with the nil value representing no error.

The "errors" Package

Creating Custom error Instances

errors.New()

Custom errors can be created by using the New() function in the "errors" package. Returns an error pointer:

import "errors"
...
errPtr := errors.New("some text")
fmt.Errorf()

The function fmt.Errorf() also creates custom error instances.

Exceptions

Exceptions (in the Java sense) are not available in Go.

An alternative mechanism can be implemented by function returning multiple values, out of which one is an error indicator.

panic

defer and finally

defer puts the function on the stack.

Panics

A panic generally indicates a programmer error (attempting to access an array index out of bounds, writing an uninitialized map, etc.) Panics can also be synthetically triggered with:

panic(message)

The panic can be caught on the stack outside the function that caused the panic, by executing recover(). Recover can be called in any upper function on the stack, or even if the function that triggers the panic, if the invocation is made with defer.


The recover() built-in function allows a program to manage behavior of a panicking goroutine. Executing a call to recover inside a deferred function (but not any function called by it) stops the panicking sequence by restoring normal execution and retrieves the error value passed to the call of panic. If recover is called outside the deferred function it will not stop a panicking sequence. In this case, or when the goroutine is not panicking, or if the argument supplied to panic was nil, recover returns nil. Thus the return value from recover reports whether the goroutine is panicking.

Error Handling Idioms

The fact that Go function can return multiple value may be used in implementing a mechanism where a function returns the "good" value and an error value, instead of an exception. If an error occurs (the error instance is not nil), you should never trust the other values being returned by the function, they should always be ignored. This is an idiomatic way of handling errors returned by functions. For a callee function A and a calling function B:

// the "callee"
func A(...) (<business-result-type>, error) {

     var result <business-result-type>

     // processing ...

     // some error occurs
     return <zero-value-for-type>, errors.New("dang")

     // all good, make sure to return all values, including a nil error
     return result, nil
}

// the calling function
func B(...) (<business-result-type>, error) {

    result, err := A(...)

    if err != nil {
        return <zero-value-for-type>, err
    }

    // process the callee's returned result ...
    // all good, make sure to return all values, including a nil error
    return result, nil
}

The fact that functions return error values can be used in conjunction with the special if syntax:

if value, error := f(); err {
   // handle err
}
else {
   // handle success
}

More about multiple return values can be found here:

Multiple Return Values