Глагол %w для ошибок

Глагол %w в функции fmt.Errorf используется для обертывания одной ошибки в другую, создавая цепочку ошибок. Это позволяет сохранить информацию о первоначальной ошибке, добавляя к ней дополнительный контекст. В первый параметр через fmt.Errorf мы передаем строку формата с глаголом %w, во второй параметр мы передаем ошибку, которую нужно обернуть.

Синтаксис

goerr := fmt.Errorf("additional context: %w", originalErr)

Пример

Давайте обернем ошибку, добавив к ней контекст:

gopackage main

import (
  "errors"
  "fmt"
)

func main() {
  originalErr := errors.New("connection refused")
  wrappedErr := fmt.Errorf("failed to connect: %w", originalErr)
  fmt.Println(wrappedErr)
}

Результат выполнения кода:

go"failed to connect: connection refused"

Пример

Давайте проверим, можно ли извлечь оригинальную ошибку из цепочки с помощью errors.Is:

gopackage main

import (
  "errors"
  "fmt"
)

func main() {
  originalErr := errors.New("database error")
  wrappedErr := fmt.Errorf("query execution: %w", originalErr)

  if errors.Is(wrappedErr, originalErr) {
    fmt.Println("original error found")
  }
}

Результат выполнения кода:

go"original error found"

Пример

Давайте создадим цепочку из нескольких ошибок и распакуем их с помощью errors.Unwrap:

gopackage main

import (
  "errors"
  "fmt"
)

func main() {
  baseErr := errors.New("timeout")
  middleErr := fmt.Errorf("read timeout: %w", baseErr)
  topErr := fmt.Errorf("request failed: %w", middleErr)

  fmt.Println(topErr)
  fmt.Println(errors.Unwrap(topErr))
  fmt.Println(errors.Unwrap(errors.Unwrap(topErr)))
}

Результат выполнения кода:

go"request failed: read timeout: timeout"
"read timeout: timeout"
"timeout"

Смотрите также

  • функцию fmt.Errorf,
    которая создает ошибки с форматированием и поддерживает обертку
  • функцию errors.Unwrap,
    которая извлекает обернутую ошибку
  • функцию errors.Is,
    которая проверяет наличие конкретной ошибки в цепочке
  • функцию errors.As,
    которая находит ошибку определенного типа в цепочке