Search
Write a publication
Pull to refresh
0
0
Вадим @Vadim_Aleks

User

Send message

Простой пример - для полного раскрытия дженериков нужно использовать any на вход. Но это небезопасно, а проверка типов внутри с последующим вызовом методов с нужными типами - собственно и зачем в итоге дженерик?

Это уже звучит не как дженерик, ведь они вычисляются на этапе компиляции, а не в рантайме. Можете привести пример?

проверки типов жрут ресурсы

В Go type cast в рантайме это один if, так что сложно в такое упереться

А как в такой схеме синхронизировать MDS с базой?

Например, объект сохранился в MDS, а в базу нет (скажем, приложение упало по OOM). Если пользователь не сделает ретрай, то объект сохранится в MDS навсегда, а база про это не узнает.

Кажется, в такой схеме нужно где-то хранить объект и мету до тех пор, пока всё это не сохранится и в БД, и в MDS

А ещё, кажется, всё таки очередь в процессре фигурирует. Вам же нужно отправить в очередь информацию о том, что появился новый объект, чтобы посчитать счетчики. Но эта проблема решается outbox паттерном, благо у вас postgres

Спасибо большое за ответы!

А какой алгоритм при создании объекта?

Предположу, что его нужно сохранить в MDS, а потом отправить запись об этом в очередь. Либо положить blob и мету в очередь

А пользователю сразу отправляется 200 OK или он ждет, пока разбирается очередь?

Как вы достигаете консистентности, например, при удалении объекта из s3db и MDS?

Может ли быть сутация, когда пользователь удалил объект, но он еще показывается в листинге?

Есть ли проблема, когда пользователь удалил объект по ключу и сразу же создал новый объект по такому же ключу?

Смотря как передавать

Если с утечкой в хип (пример, при вызове метода интерфейса, замыкания и тд), то пусть структура хоть 300 байт весит — всё равно лучше передать по значению. Есть еще дополнительные нюансы, но в целом правило такое: лучше всегда передавать по значению там, где это возможно. Так GC и latency скажут спасибо

Если структура гарантировано не утечёт в хип, то да, лучше по указателю если структура занимает от двух машинных слов

обработку исключений в специальное место лишают своих пользователей важного

Что важного можно передать пользователю после исключительной ситуации? Максимум trace_id, который достаётся из заголовков. Остальное ему не надо

А если надо, то можно явно написать Middleware даже в том же Go

А как при 1-ом подходе возвращать несколько вариантов результата функции? Например, хочется различать UserNotFound от UserNotActive или UserEmailNotVerified - плохой пример

Да. Разработчик быстро исправит эту функцию если приложение станет невозможно запустить.

Не быстро) В больших компаниях, где настроен бюрократичный CI/CD, потребуют от вас создать задачу, получить 2 апрува, выкатиться на dev/stg а лишь потом, с канареечным деплоем выкатываться на prod. И всё это время приложение по сути будет недоступно. Даунтайм на проде около часа.

тесты помогают не запускать каждый раз приложение

Идеальный случай) Никто не делает 100% покрытие кода в приложениях.

Кстати, исключения плохо влияют на покрытие кода тестами. Цифра может быть 100%, но тесты все случаи не покрывают. Вы уже несколько раз упоминали, что исключения не надо обрабатывать, но часто ими пользуются неправильно. Если вы импортировали библиотеку, где throw на каждый чих - идите обрабатывать через try-catch :). В итоге получается, что нужно лезть и исходники библиотеки, чтобы понять как, когда и чем она выплёвывается

Generic'и в Go есть, но реализовать check() в том виде, что вы указали, всё равно не выйдет. Нужна поддержка tuple'ов скорее

Еще не затронулась тема, что не всегда ясно какое исключение может выкинуть функция. Не всегда ясно нужно ли писать try-catch. При http запросе, если status_code != 200 - это исключение? Приходится читать исходники и документацию, чтобы уточнить. В Rust это решается тем, что все возможные типы ошибки обычно описывают в Enum'е.

В Java, кажется, первая проблема решается декларированием возможного (или даже конкретного?) исключения у каждого метода. И компилятор явно просит обработать такой случай

нет смысла кидать исключение и пытаться обрабатывать его, можно программу просто завершить

В корне не согласен. Если приложение долго запускается, то давайте мы его завершим, чтобы оно опять прогревалось, только потому что одна функция одного обработчика выбросила исключение?

Подозреваю, чтобы в слое транспорта писать не catch(PgRowNotFound), а catch(UserNotFound)

А, речь была про битые ссылки после введения арен, теперь понял посыл

А как это можно воспроизвести без cgo и unsafe?

В теории, да. Чтобы наверняка, можно установить GOGC=off

А приведённый "отличный новый код" это просто ужас, код на С и то лучше чем на go.

Вам не предлагают отныне и навсегда пользоваться arena-аллокаторами и забыть про старый API. Важно понимать, что арена-аллокаторы нужны не всем. Любой низкоуровневый код выглядит уродливо, будь то Java, Haskell, Go, C

битые ссылки

В смысле nil-указатели? Так используйте меньше указателей. Часто вижу []*Object и прочее таскание указателей по всем функциям, из-за чего страдает и программист, и GC)

По части nil-указателей у меня лишь болит от использования неинициализированной map'ы. Так легко объявить и так легко забыть инициализировать)

программы на го текут пуще прежнего

А что именно текло: приложения или библиотека? У меня Go-приложения текли только когда неправильно использовался unsafe)

Подскажите, а есть ли какие-то ограничения на бенчмарк? Например, можно ли распараллелить? Можно ли вставить, например, sync.Pool ради переиспользования объектов?

я выше упоминал CardRaytracerBenchmark

Посмотрел эти бенчмарки и решил немного покрасноглазить.

  1. В Go реализации писать в stdout без буфера, а в java с буфером - грязный ход. И зачем в цикле что-то в output выводить, там IO мерят что ли?

  2. В скриптах run.sh в java реализации весь вывод идет в /dev/null, в гошном run.sh такого нет.

  3. Очень много лишний лишних объектов просто ради объектов (тестировали аллокатор?). Раз уж речь про GC, то ради интереса снял профиль CPU у Go приложения, так там GC даже в TOP 20 функций нет

Очередные бенчмарки ни о чем. Кстати, на моей машине гошная реализация с /dev/null выдала меньше времени, чем пару раз прогнанная джавовая. Если без изменений запускать run.sh, то да, java c /dev/null быстрее чем Go с терминальным stdout))

И стоит упомянуть, что java-код явно писал джавист. Про Go реализацию я бы так не сказал, иначе хотя бы не копировались структуры в функции\методы зазря, а передавались по ссылке

за такой промежуток времени вы не можете проникнуться никаким языком

Что значит "проникнуться"? Знать детали реализации рантайма? Понимать как писать идиоматичный код?

И из вашего же сообщения:

вы с шарпа на go переходите - это не совсем отражает то, что на самом деле произошло

А произошло следующее. Вы занялись шарпом <...>, перешли на другой язык

то есть, человек перешел с шарпа на го. В чем автор не прав?)

1

Information

Rating
Does not participate
Registered
Activity

Specialization

Backend Developer
Senior