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
- Host: GitHub
- URL: https://github.com/iimos/go-check-err-chains
- Owner: iimos
- License: apache-2.0
- Created: 2021-05-06T21:02:41.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2024-01-28T15:16:11.000Z (over 2 years ago)
- Last Synced: 2024-06-20T15:00:38.683Z (almost 2 years ago)
- Topics: error, go, go-error-handling, go-errors, go-linter, golang, linter, logging
- Language: Go
- Homepage:
- Size: 18.6 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README-ru.md
- License: LICENSE
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`.
Второй вариант инженеру проще и читать и писать.
- Логи удобно грепать
А главный минус подхода в том что нужно следить за согласованностью имени пакета/функции
и текста ошибок/логов, ведь при переименовании функции нужно не забыть поменять
все ошибки/логи.
Именнно эту проблему и решает этот линтер.