Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

07.02.2025

Особливості помилок в Go: квазістектрейс

Вже пробачте, що я про Go зарядив (спойлер: завтра буде ще й оголошення невеличкого проєкту на Go), але сьогодні усвідомив один цікавий аспект. Цікавий скоріше тим, хто на Go не пише.

В Go помилка — це, в першому наближенні, так званий “таврований рядок”. Тобто зміст помилки — це рядок, але належність до типу error чітко відрізняє її від “просто рядка”. У звичайних помилок немає більше нічого.

(Зокрема, в error немає детальної типізації (ну як, вона може бути, бо error - це тільки інтерфейс, але це буде нестандартно.) Щоб впізнати потрібну помилку, її роблять константою, та порівнюють за значенням.)

Також в error немає стектрейсу (є бібліотеки, які його додають, але не загально прийнятні.) Але замість стектрейсу, в Go є загортання помилок. Коли вам повертають помилку, традиційно функцією fmt.Errorf додають до неї власну інформацію.

res, err := http.Request(myURL)
if err != nil {
  return fmt.Errorf("loading URL failed: %w", err)
}

На верхньому рівні отримуємо щось на кшталт: failed to calculate balance: failed to load user: database request failed: io timeout. Так виглядає типова помилка у Go. Та ось сьогодні збагнув, що це ж той самий стектрейс! Тільки ручної роботи. Можна грепати його частини та знайти, звідки вони.

З першого погляду, незрозуміла поробка. Але я знайшов пару переваг, порівняно зі стектрейсами. По-перше, такий загорнутий рядок відносно компактний, що важливо для логування. По-друге, стректрейси псуються при рівночасності (класична проблема інших мов), а загортання помилок — ні, його й з рівночасністю можна робити так, як зручно.

Власне, тому важливо завжди загортати помилки. Навіть є лінтер wrapcheck, який на це перевіряє.