Ошибки как значения: обёртка через %w, errors.Is и errors.As
В Go ошибка — обычное значение, реализующее интерфейс error с единственным методом Error() string. Возврат ошибки виден в сигнатуре, и обработать её обязан вызывающий. Чтобы не терять контекст по пути наверх, ошибку оборачивают: fmt.Errorf("чтение конфига: %w", err) создаёт новую ошибку, внутри которой лежит исходная. Именно %w, а не %v — с %v текст сохранится, а связь потеряется. Проверять обёрнутую цепочку нужно двумя функциями: errors.Is(err, target) ищет конкретное значение-ошибку (os.ErrNotExist, свои var ErrNotFound = errors.New(...)), а errors.As(err, &target) ищет ошибку конкретного типа и заполняет переменную, чтобы добраться до полей. Сравнение через == работает только с необёрнутыми ошибками и потому ломается при первом же добавлении контекста. Правило оформления: текст ошибки пишется с маленькой буквы и без точки, потому что он почти всегда станет частью более длинной строки.