int): (*User, error)
Получается же 3 возможных состояния: пользователь найден, пользвоатель не найден, возникла ошибка в рантайме(например ошибся в sql запросе).
подскажите как Вы в таких случаях поступаете: три параметра возвращаете, каким-то механизом понимаете, где выходной error соответствует ошибке в sql запросе, а где тому, что пользователь не найден? Или может если пользователь не найден, возвращаете пустую структуру, а если ошибка, то nil?
Грубо говоря как отделяете доменные ошибки от инфраструктурных
Определить свою ошибку ErrNotFound и вернуть её.
А "пользователь не найден" - это ошибка? Если да, то возвращать ошибку такую, а если нет, то вернуть nil, nil к примеру
И потом везде просто прокидывать ее наверх и в хендлере решать, что вывести пользователю? Просто видел, что многие через errors.Wrap на каждом этапе добаляют контекст, если с помощью errors.Wrap добавлять контекст то наверху уже не получится проверить что ошибка именно ErrNotFound
Через errors.Is() получится
врапаем ошибку и перекидываем выше
См. errors.Is, errors.As (https://go.dev/blog/go1.13-errors)
еще надо подумать надо ли возвращать указатель (вместо значения), как правило не надо и можно сэкономить аллокацию а заодно улучшить иммутабельность кода
может посоветуете статейку которую на эту тему почитать можно? Мне казалось наоборот, если возвращается ссылка, то значение не копируется и соответственно нет аллокации
в effective go написано где лучше возвращать адрес и где лучше возвращать копию
Если в двух словах, то если используется указатель, то память выделяется в куче, с последующим обслуживанием garbarge collector, что иногда медленнее. Если небольшая структура передаётся копией, то это кладётся в стэк и это может оказаться быстрее. На больших структурах наоборот.
https://stackoverflow.com/a/23551970/329463
https://go101.org/optimizations/0.3-memory-allocations.html
все параметры функций в Go (до недавнего времени) передаются через стек. и не имеет значения это структура или указатель - данные будут скопированы стек - значение имеет только размер. что касается того где будет алоцирована память - это определяет escape analysis.
Я немного про другое. Про то, что лучше, передавать ли ссылку на структуру, или саму структуру.
в Go нету понятие ссылки как в C++
Отлично. А что есть?
есть указатели
А p := &myvar разве не взятие ссылки? ☺️
а как же передача через регистры?
и что, пусть так, тогда указателем вы стек будете экономить, int вместо структуры
Ну я про память, прошу прощения, что не пишу длинные развёрнутые юридически верефицированные тексты 😂
Ну а аллокация памяти и GCне смущает?
Тем более стек ограничен в размере. ☺️
Чем ограничен?
Аллокация в любом случае будет, что в стеке выделение идет, что в куче. И вообще, если так это нравится, ковырятся, в какой именно памяти, то пишите в сях В го нет разделения на стэк и кучу
Через регистры - обычная практика
Причем тут размер физической страницы. Под стек выделяется виртуальная память
Тема вопроса коллеги была как лучше передавать структуру в функцию, как ссылку или напрямую. Через регистры ещё быстрее будет.
при том что виртуальная память состоит из страниц реальной памяти и контролировать ее расход (как и права доступа на самом деле) проще аппаратными средствами процессора, а не программным кодом
через регистры не получится передать структуру целиком совсем :)
Вы заблуждаетесь. Для стека точно такие же права, как и для кучи
Коллега, вы опять что-то несёте. Нам уже объясняли сегодня, что "в го нет разделения на стэк и кучу!" 😊
Я несу только светлое, доброе вечное 😂
Больше того, если мне не изменяет склероз, до в этих ваших линуксах стек начального потока приложения при его запуске просто указывает на конец кучи
cat /proc/self/maps 559538c72000-559538c74000 r--p 00000000 103:03 536872090 /usr/bin/cat 55953a665000-55953a686000 rw-p 00000000 00:00 0 [heap] 7ffd07964000-7ffd07985000 rw-p 00000000 00:00 0 [stack] склероз Вам явно изменяет :)
да, ошибся https://ibb.co/0VDkss0
я просто оставлю это здесь https://go.dev/doc/faq#stack_or_heap
но интересно что 024c4000-024e5000 rw-p 00000000 00:00 0 [heap] c000000000-c000200000 rw-p 00000000 00:00 0 c000200000-c000600000 rw-p 00000000 00:00 0 c000600000-c000800000 rw-p 00000000 00:00 0 c000800000-c004000000 ---p 00000000 00:00 0 ... 7ffc83882000-7ffc838a3000 rw-p 00000000 00:00 0 [stack] func reader(c <-chan int) { for { i := <-c fmt.Println(i, &i) } } ---- 539320 0xc00019c300
Обсуждают сегодня