Comments 20
Опять фэйл. Где стектрейс? Где множественное наследование ошибок? Всё ещё использую merry

Стектрейс есть в панике, для всего остального есть логи, Объединенные контекстом

Не надо путать божий дар с яичницей. При чём тут паника и логи если речь идёт об ошибках? Ошибки в сторонних либах в месте их возникновения нельзя ни залоггировать ни превратить в панику. Стектрейс — единственный способ точно установить где именно возникла ошибка. Стектрейс есть в любом уважающем себя рантайме в исключениях. Тот факт, что по умолчанию в любой ошибке, созданной с помощью fmt.Errorf и errors.New, нет стектрейса — это грёбаный стыд и феерический косяк разработчиков голанга. Один из самых дебильных способов сэкономить на спичках и сломать ноги в темноте
Стектрейс — единственный способ точно установить где именно возникла ошибка.

Вы, простите, поиском по коду пользоваться умеете?


Стектрейс есть в любом уважающем себя рантайме в исключениях.

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


В Go стек динамического размера, что делает исключения еще дороже. Вы предлагаете пожертвовать скоростью ради сомнительной выгоды.


нет стектрейса — это грёбаный стыд и феерический косяк разработчиков голанга

В первых версиях errors стектрейс был, но его убрали как раз по той самой причине что а) стектрейс на каждую ошибку это довольно дорого б) непонятно как настроить инспекцию, ведь далеко не всегда нужен стектрейс, а достаточно вывода самой ошибки. Можете глянуть /x/xerrors — там стектрейс до сих пор остался.

Каким образом умение поиска по коду поможет найти место возникновения ошибки во внешней библиотеке?
захват фрейма не самая дешевая операция
прикрепить к ошибке несколько байт дебаг-символов — дорогая операция?? с чего вы это взяли? Где бенчмарки?
развертка стека операция по определению недешевая.
совершенно наплевать на развёртку стека. она происходит один раз на самом верху в момент логгирования ошибки
Каким образом умение поиска по коду поможет найти место возникновения ошибки во внешней библиотеке?

А чем отличается поиск кода в своих проектах и поиска кода в чужих? В Go все довольно просто — ищите где создается ошибка с нужным вам текстом и как она прокидывается.


прикрепить к ошибке несколько байт дебаг-символов — дорогая операция?? с чего вы это взяли? Где бенчмарки?

https://play.golang.org/p/xo3FBPqm1AK 600 ns против 20 ns.


совершенно наплевать на развёртку стека. она происходит один раз на самом верху в момент логгирования ошибки

Почитайте про stack unwinding и как работает panic/recover/defer и что конкретно за вас делает рантайм, чтоб у вас не утекали ресурсы.

ищите где создается ошибка с нужным вам текстом и как она прокидывается.

Ошибка может создаваться в специально предназначенном для этого методе, который вызывается из 50 мест.

Я не большой сторонник стектрейсов в ошибках (все-таки, это не исключения), но, помнится мне, в merry была ещё одна интересная возможность — завернуть ошибку err1 в другую ошибку err2 используя Cause. При этом остается возможность получить и err1 и err2 как отдельные ошибки и достать из них нужную информацию.


Без подобного враппинга идея в Go 1.13 кажется неполной.

В том то и дело, что там есть только стектрейс и возможность заврапить ошибку с сохранением стектрейса. Возможности добавить в ошибку какой-то дополнительный контекст, кроме сообщения, я не вижу.

Есть библиотеки для ошибок на много лучше — github.com/ansel1/merry

Речь идёт о том, чтобы включать стектрейс в любую ошибку, созданную функциями errors.New и fmt.Error.
Не совсем понял. Могу ли упаковать ошибку в ошибку?
func file{
f, err := os.Open(filename)
if err != nil {return fmt.Errorf("%w", err) }

func catalog{
f, err := os.Open(filename)
if err != nil {return fmt.Errorf("%w", err) }

func someFunc{
err1, f1 := file() 
err2, f2 := catalog()
return fmt.Errorf("%w %w", err1, err2)
Так можно?

Ну вот в фмт можно указать. ("%v %v", " значение 1, значение 2). Здесь так можно? И потом получить err.Is(знч1, знч2, ошибка1, ошибка2)

Стандартными средствами — нет, так как агрегирование (когда функция одновременно возвращает множество ошибок) хоть и обсуждалось, но придти к единому решению пока не смогли. Но можно быстро накидать самому, например. Однако и у этой реализации есть минусы/особенности — так, например, если функция возвращает две ошибки одного типа (например оба os.Open вернули *os.PathError) то errors.As/Is позволит посмотреть только одну из них. Способы решения для этой проблемы то-же есть — либо добавить к типу multiError итератор, либо завести собственный тип реализующий ошибку, для функции someFunc у которого тонко настроить As/Is. Если хотите, могу через личку уточнить как сделать оба подхода.
всё это можно. Но. В someFunc:
errors.Is(fmt.Errorf("%w %w", err1, err2), err1) == err2 //true
errors.Is(fmt.Errorf("%w %w", err1, err2), err1) == err1 //false
Нет. Читаем документацию fmt.Errorf:
It is invalid to include more than one %w verb or to supply it with an operand that does not implement the error interface.
В чём это противоречит тому, что я написал, и с чего вы взяли что я не читал документацию?
Вот кто ставит минусы. Не за себя прошу. И за вопрос, и за ответ минус. Может тогда развернете свою мысль, раз вы гуру в Golang.
Only those users with full accounts are able to leave comments. Log in, please.