Go Error Wrapping: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
Line 7: Line 7:
Error wrapping and returning the result to the upper layer is one of the common error handling patterns in Go. The others are [[Go_Language_Error_Handling#Deal_with_the_Consequences_and_Continue_the_Flow|fully handling the error without returning it]], simply [[Go_Language_Error_Handling#Handle_the_Error_as_Opaque_and_Return_It_Unmodified|returning it without any modification]], and [[Go_Language_Error_Handling#Annotate_the_Error|returning a new annotated error]].
Error wrapping and returning the result to the upper layer is one of the common error handling patterns in Go. The others are [[Go_Language_Error_Handling#Deal_with_the_Consequences_and_Continue_the_Flow|fully handling the error without returning it]], simply [[Go_Language_Error_Handling#Handle_the_Error_as_Opaque_and_Return_It_Unmodified|returning it without any modification]], and [[Go_Language_Error_Handling#Annotate_the_Error|returning a new annotated error]].


The pattern consists in wrapping an error returned by the underlying layer into an "outer" error instance. This is typically done to add information relevant to the context that caught the error being processed. However, wrapping the error is more than [[#Annotate_the_Error|error annotation]], because it involves embedding an actual error instance, preserving its unique identity, instead of concatenating strings.
The pattern consists in wrapping an error returned by the underlying layer into an "outer" error instance. This is typically done to add information relevant to the context that caught the error being processed. However, wrapping the error is more than [[Go_Language_Error_Handling#Annotate_the_Error|error annotation]], because it involves embedding an actual error instance, preserving its unique identity, instead of concatenating strings.


=Wrap the Error=
=Wrap the Error=

Revision as of 20:08, 28 December 2023

Internal

Overview

Go error mechanism allows "wrapping" error instances into other error instances, while preserving the wrapped error identity. This pattern supports building an error tree that is useful in preserving context.

Error wrapping and returning the result to the upper layer is one of the common error handling patterns in Go. The others are fully handling the error without returning it, simply returning it without any modification, and returning a new annotated error.

The pattern consists in wrapping an error returned by the underlying layer into an "outer" error instance. This is typically done to add information relevant to the context that caught the error being processed. However, wrapping the error is more than error annotation, because it involves embedding an actual error instance, preserving its unique identity, instead of concatenating strings.

Wrap the Error

Inspect the Error Tree

TO DEPLETE

An error instance can be wrapped with fmt.Errorf() and %w conversion character.

if err != nil {
  return fmt.Errorf("additional information: %w", err)
}

The wrapped error message, assuming that the original error is "initial information", with be:

additional information: initial information

Document errors.Unwrap()

Checking for Wrapped Errors

A wrapped error can be identified in an enclosing error with the errors.Is(<outer_error>, <sought_for_error>) function.

Need to understand errors.Is(), error tree, wrapping and unwrapping.

var BlueError = errors.New("some information")
var GreenError = errors.New("some information")

...

// wrap the error in an outer error
outerError := fmt.Errorf("addtional info: %w", BlueError)

if errors.Is(outerError, BlueError) {
  fmt.Println("found blue error")
}

if errors.Is(outerError, GreenError) {
  fmt.Println("found green error")
}

BlueError is correctly identified, even though both BlueError and GreenError carry the same string. How?