An open API service indexing awesome lists of open source software.

https://github.com/iimos/go-check-err-chains

Go linter that checks that the error text contains a prefix indicating the package/function/method where the error occurred
https://github.com/iimos/go-check-err-chains

error go go-error-handling go-errors go-linter golang linter logging

Last synced: 5 months ago
JSON representation

Go linter that checks that the error text contains a prefix indicating the package/function/method where the error occurred

Awesome Lists containing this project

README

          

# go-check-err-chains

Линтер проверяет что текст ошибок содержит префикс указывающий на пакет/функцию/метод в котором произошла ошибка.

Проверка проводится только для экспортируемых функций.

Пример:
```go
package pkg

func Get(key string) error {
id, err := strconv.Atoi(key)
if err != nil {
return errors.New("pkg.Get: %w; key=%s", err, key) // good
}
if empty {
return sql.ErrNoRows // bad
}
return nil
}
```

## Зачем

Этот линтер – попытка навести порядок влогах.

По логам часто не понятно где произошла проблема.

У этой проблемы уже есть есть пара решений, но все имеют существенные недостатки:

1. Использовать логер снабжающий записи указанием на файл и строку где лог был написан.

Файл и номер строки логер указать может, но это будет место где вызвали log.Error,
а не место в котором произошла ошибка.

Это значит что ошибки нужно логировать прямо там где они произошли.
В итоге логи начинают писать повсюду и с большой избыточностью.

Одна ошибка генерирует несколько похожих сообщений про одну и ту же ошибку
и в каждом сообщении немного свой контекст и чтобы увидеть полный контекст
необходимо собрать все эти записи.

2. Использовать для ошибок сторонние библиотеки типа [pkg/errors](https://github.com/pkg/errors)

Есть множество библиотек которые сохраянют стек вызовов при создания ошибки.

Это не плохой подход, но есть ряд минусов:
- повсюду нужно использовать одну определенную библиотеку для ошибок
- плохо сочетается с нативным [врапингом через %w](https://go.dev/blog/go1.13-errors)

На данный момент оптимальным компромисом кажется идти идиоматическим путем принятым
в стандартной библиотеке:

Примеры ошибок из стандартной библиотеки:
- strconv.Atoi: parsing "x": invalid syntax
- plugin.Open("file.so"): realpath failed
- bytes.Buffer: too large
- open file.go: no such file or directory
- strings.Builder.Grow: negative count

Видно что строгой схемы нет, но паттерн прослеживается: вначале имя пакета/метода/функции, затем двоеточие и далее подробности.

```go
package pkg

func Get(key string) error {
id, err := strconv.Atoi(key)
if err != nil {
return errors.New("pkg.Get: %w; key=%s", err, key)
}
// ...
}
```

`pkg.Get("abc")` дает ошибку:
```
pkg.Get: strconv.Atoi: parsing "abc": invalid syntax; key=abc
```

У такого подхода ряд плюсов:

- Хорошо стыкуется с ошибками стандартной библиотеки

- Дружит с врапингом

- Писать текст ошибки проще:

`failed to get package cause key abc is not valid ...` vs `pkg.Get: strconv.Atoi: parsing "abc": invalid syntax`.

Второй вариант инженеру проще и читать и писать.

- Логи удобно грепать

А главный минус подхода в том что нужно следить за согласованностью имени пакета/функции
и текста ошибок/логов, ведь при переименовании функции нужно не забыть поменять
все ошибки/логи.

Именнно эту проблему и решает этот линтер.