Обработка ошибок является важным аспектом разработки надежных приложений на любом языке программирования. В Go разработчикам часто нужно различать исправимые и неисправимые ошибки, чтобы решить, следует ли перезапустить приложение или завершить его. В этом посте мы рассмотрим, как использовать глагол %w в обработке ошибок для переноса и определения исправимых и неисправимых ошибок в приложении Go.

Обзор кода

Предоставленный пример кода имитирует приложение обработки задач, которое сталкивается со случайными устранимыми и неустранимыми ошибками. Приложение использует глагол %w для переноса этих ошибок и обрабатывает их соответствующим образом:

package main

import (
 "errors"
 "fmt"
 "math/rand"
 "time"
)

var (
 ErrRecoverable   = errors.New("recoverable error")
 ErrUnrecoverable = errors.New("unrecoverable error")
)

func processTask(taskID int) error {
 // Simulate random errors for demonstration purposes
 randomErr := rand.Intn(10)
 fmt.Printf("randomErr: %d\n", randomErr)
 switch randomErr {
 case 0:
  return fmt.Errorf("task %d failed with %w", taskID, ErrRecoverable)
 case 1:
  return fmt.Errorf("task %d failed with %w", taskID, ErrUnrecoverable)
 default:
  fmt.Printf("Task %d processed successfully\n", taskID)
  return nil
 }
}

func main() {
 rand.Seed(time.Now().UnixNano())
 const maxTasks = 100

 for i := 0; i < maxTasks; {
  err := processTask(i)
  if err != nil {
   if errors.Is(err, ErrRecoverable) {
    fmt.Printf("Recoverable error occurred: %v. Restarting app...\n", err)
    continue
   } else if errors.Is(err, ErrUnrecoverable) {
    fmt.Printf("Unrecoverable error occurred: %v. Terminating app...\n", err)
    break
   }
  }
  i++
 }
}

Использование %w для переноса ошибок

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

return fmt.Errorf("task %d failed with %w", taskID, ErrRecoverable)
return fmt.Errorf("task %d failed with %w", taskID, ErrUnrecoverable)

Обработка обернутых ошибок

В функции main мы обрабатываем ошибки, проверяя, являются ли они обернутыми ошибками, используя функцию errors.Is. Это позволяет нам идентифицировать исходный тип ошибки, сохраняя при этом дополнительный контекст, предоставляемый сообщением об ошибке:

  if err != nil {
   if errors.Is(err, ErrRecoverable) {
    fmt.Printf("Recoverable error occurred: %v. Restarting app...\n", err)
    continue
   } else if errors.Is(err, ErrUnrecoverable) {
    fmt.Printf("Unrecoverable error occurred: %v. Terminating app...\n", err)
    break
   }
  }

Заключение

В этом посте мы продемонстрировали, как использовать глагол %w в обработке ошибок Go, чтобы различать исправимые и неисправимые ошибки. Оборачивая и идентифицируя определенные типы ошибок, разработчики могут создавать более отказоустойчивые приложения, которые могут разумно перезапускать или завершать работу в зависимости от характера возникшей ошибки. Этот подход способствует улучшению методов обработки ошибок, помогая разработчикам создавать приложения, которые являются более надежными и адаптивными к различным сценариям возникновения ошибок. Благодаря сочетанию обернутых ошибок и встроенных в Go функций проверки ошибок, таких как errors.Is, проще, чем когда-либо, реализовать сложные стратегии обработки ошибок в ваших приложениях Go.

Если вам нравится читать статьи на Medium и вы заинтересованы в том, чтобы стать участником, я буду рад поделиться с вами своей реферальной ссылкой!

https://medium.com/@adamszpilewicz/membership