
Привет, Хабр!
Сегодня разберём, как устроен reflect.Value
изнутри и что на происходит, когда вы вызываете .Field(i)
.
Компилируемый, многопоточный язык программирования
Привет, Хабр!
Сегодня разберём, как устроен reflect.Value
изнутри и что на происходит, когда вы вызываете .Field(i)
.
Go — язык, который ценится за простоту и чёткость. Однако даже при минимальном синтаксисе здесь есть нюансы. Особенно это касается работы с функциями и методами. В этой статье хочу поделиться личными наблюдениями и выводами по нескольким ключевым темам: выбор типа получателя, использование именованных параметров результата, распространённые ошибки при возврате nil, проблемы с файлами в качестве входных данных и поведение defer
.
ps. Обложку нейронка сгенерировала. Очень странно, но мне понравилось.
Привет, Хабр!
В статье рассмотрим, как реализовать Template Method-паттерн в Go без наследования, зачем он вообще нужен.
В данной статье представлен авторский подход к унификации и централизации механизма обработки ошибок в HTTP-обработчиках веб-сервисов, разработанных на языке Go. Статья подробно рассматривает ограничения традиционных методов обработки ошибок, ведущие к дублированию кода и снижению поддерживаемости. Предлагается новый архитектурный паттерн, включающий использование специализированной сигнатуры функций-обработчиков, кастомного типа ошибки HTTPError для инкапсуляции статуса ответа, сообщения для клиента и внутренней ошибки для логирования, а также Middleware-адаптера для интеграции с фреймворками net/http и Gin. Данный подход демонстрирует повышение читаемости кода, упрощение отладки и обеспечение консистентности ответов API, что представляет собой значимый вклад в практику разработки бэкенд-сервисов на Go.
Забудьте о том, что Docker — это некий таинственный инструмент исключительно для DevOps-инженеров. В современном мире разработки Docker стал таким же незаменимым швейцарским ножом, как Git или ваш любимый редактор кода. Он позволяет любому разработчику писать код, который будет одинаково работать на машине коллеги, на тестовом стенде и в продакшене, забыв о кошмаре "а у меня на машине все работает". Если вы еще не погрузились в мир контейнеризации или вам нужен удобный источник команд, эта статья — ваш экспресс-билет.
Всем привет! В данной статье я поделюсь своим опытом написания сервиса. Я не являюсь опытным или профессиональным разработчиком, я пишу свой проект и мои решения могут быть не самыми оптимальными. Эта статья состоит в основном из моих решений при написании сервиса, что могут быть не идеальными. Мой путь не является правильным и потому - судите "строго". Так же порекомендую прочитать предыдущие мои статьи.)
В настоящее время резко возрос спрос на контейнеры, используемые в продакшене для эксплуатации больших энтерпрайз-приложений. Как правило, они развёртываются в Docker. Docker де-факто стал основной технологией для работы с контейнеризованными приложениями. Но на основе чего он построен? Как он контейнеризует приложения? В данной статье постараемся ответить на эти вопросы.
Привет, Хабр!
Сегодня разберёмся, зачем Go-проекту слой Application / Use-Case: как он герметично изолирует бизнес-логику, позволяет переключаться между HTTP, gRPC, Cron-джобами и очередями, а заодно экономит тесты и нервные клетки.
Ошибки в приложениях неизбежны, но мы можем их смягчить и упростить отладку. Но как выбрать правильный способ обработки?
В этой статье предлагаю разобраться, как организовать работу с ошибками в Go так, чтобы они не просто сигнализировали о проблеме, но и помогали быстро её локализовать, воспроизвести и устранить. Рассмотрим инструменты и ограничения Go, обсудим подходы к обработке ошибок, а в финале сформулируем регламент, который поможет выбрать оптимальный способ работы с ошибками в разных сценариях.
Я структурировал способы обработки в зависимости от контекста — ситуации и типа программ, в которой возникает ошибка. Типы разделений — условные, в реальных задачах рекомендую опираться на требования к ошибке:
· Библиотека — узкоспециализированная программа, основной потребитель разработчик.
· Command Line Interface — консольные утилиты, где пользователем может быть кто угодно, а даже если это программист, то он не обязан понимать как CLI устроен внутри.
· Сервисы — Worker, WEB/API/RPC-сервисы и др.
Go не признаёт сложных развесистых фреймворков — и это правильно. Любой инструмент должен быть настолько очевидным, чтобы разработчики сразу видели пользу от его применения.
И если вы сталкивались на больших legacy-проектах с хаосом в обработке и логировании ошибок — когда одна и та же ошибка дублируется в логах на каждом уровне, когда непонятно где обрабатывать ошибку, а где передавать дальше, когда тесты превращаются в кромешный ад из-за необходимости мокать каждый возможный путь ошибки — тогда возможно пригодится то, что я хочу предложить.
В этой статье я хочу погрузиться в то, как работают некоторые структуры (далее ниже) в ГО. Хотя я и работаю с ГО уже 3й год, все равно есть вещи, в которые интересно погружаться. Хочу отметить, что я не буду погружаться прям сильно в реализацию того как устроены map и slice, скорее на столько, что бы понимать как они ведут себя и почему. Такое часто могут спрашивать на собеседованиях или это может писать более качественный и безопасный код.
Итак на сколько мы знаем (я надеюсь, что и вы читаете статью уже со знанием ГО) в ГО можно разделить типы переменных глобально на 2 группы
В эпоху становления асинхронного программирования JavaScript-разработчики столкнулись с явлением, получившим название "callback-hell" — бесконечной вложенностью функций обратного вызова. Хотя с точки зрения функционального программирования функции являются полноправными гражданами первого класса, принцип "всё хорошо в меру" никто не отменял. Появление Promise и механизма async/await стало спасительным решением этой проблемы.
В мире Go у нас есть более элегантные инструменты — каналы и горутины. Однако совершенству нет предела, и здесь нас поджидает другая ловушка — "error-hell". Новички в Golang часто приходят в недоумение от того, что идиомы языка требуют обработки ошибок буквально на каждом шагу.
Строки — одна из самых часто используемых структур данных в любом языке программирования. И в Go они повсюду: от простых приветствий вроде "Hello, World!"
до сложных парсеров, логгеров и сетевых протоколов. На первый взгляд, с ними всё просто: создал, склеил, обрезал — и пошёл дальше. Но как это часто бывает, под простотой скрываются тонкости, игнорирование которых может привести к ошибкам и снижению производительности.
Go предлагает удобные, но специфичные механизмы работы со строками. Они тесно связаны с понятиями Unicode, UTF-8, рун, неизменяемости и байтовых представлений. Понимание этих механизмов позволяет не только избежать типичных подводных камней, но и писать более эффективный код.
Наверняка вам уже не раз попадалась на глаза статься, в которой рассказывают о том, какие пакеты и файлы нужно создать в вашем проекте, чтобы код получился легко расширяемым и поддерживаемым. Эта еще одна статья такого рода, посвященная декомпозиции проекта go на минимально зависимые друг от друга части. В качестве движущих сил декомпозиции будут использоваться следующие известные практики:
- архитектура слоев;
- предметно-ориентированное проектирование (DDD);
- разделение команд и запросов (CQS);
- архитектура портов и адаптеров.
Также будет затронута тема именования файлов .go и вопросы связности (low coupling/high cohesion).
Всем привет! В данной статье я поделюсь своим опытом написания сервиса. Я не являюсь опытным или профессиональным разработчиком, я пишу свой проект и мои решения могут быть не самыми оптимальными. Эта статья состоит в основном из ошибок, которые я совершил. Мой путь не является правильным и потому - судите "строго".
Go-разработчики часто сталкиваются с парадоксом: изначально простой и понятный проект со временем превращается в сложный для поддержки монолит.
✔️ Бизнес-логика оказывается размазана между слоями?
✔️ Замена базы данных требует переписывания половины кода?
✔️ Новым разработчикам требуется недели, чтобы разобраться в проекте?
В этой статье мы разбираем практическое применение DDD и Clean Architecture в Go. Обсуждаем возможный стандарт структуры микросервиса. Оптимизируем существующие.
🔥 Для разработчиков, которые хотят создавать проекты, остающиеся поддерживаемыми даже через годы развития.
TLDR: LLM неплохо справляются с кодингом, но в больших проектах они пишут запутанный сумбур. Я уменьшил объём использования ИИ при кодинге и вернулся к работе головой, ручке и бумаге.
Несколько месяцев назад мне нужно было создать новую инфраструктуру для моего SaaS, потому что связка из PHP+MySQL перестала отвечать нашим требованиям. Мне не терпелось воспользоваться этой возможностью, чтобы максимально задействовать все новые LLM, с которыми я экспериментировал. Поэтому я временно отказался от должности разработчика ПО, став сам себе продакт-менеджером. Я обсуждал с Claude технологии, проводил собственные исследования и спустя много итераций составил план. В итоге я решил использовать Go+Clickhouse.
Когда настала пора начинать кодить, я попросил Claude сгенерировать большой и сложный файл markdown с описанием моей старой инфраструктуры, желаемой новой инфраструктуры, перечислением того, чего я хочу достичь, почему мне это нужно и так далее.
Потом я закинул это всё в Cursor Notepads и начал составлять промпты. Cursor пишет код, я собираю и тестирую его. Меня вполне устраивало происходящее, кодовая база была не самой чистой, но вроде работала. Мне важнее была скорость разработки, а не чистота кода — мои бизнес-клиенты SaaS сказали, что им нужны определённые данные, а эта новая инфраструктура была единственным способом их доставки. У меня было ещё несколько потенциальных клиентов, ожидающих моего сообщения о том, что всё готово, чтобы можно было приобрести тарифный план. Пока всё не готово, я в буквальном смысле каждый день теряю деньги.
При работе с кластерами PostgreSQL, особенно в конфигурациях с высокой доступностью (High Availability, HA), разработчики часто сталкиваются с ошибками типа "cannot execute INSERT in a read-only transaction". Эти ошибки возникают, когда приложение пытается выполнить операцию записи на узел, который в данный момент является репликой (read-only). Особенно остро эта проблема проявляется в моменты переключения мастера: пул соединений вашего приложения может все еще содержать коннекты к бывшему мастеру, ставшему репликой, или же балансировщик может направить новый запрос на запись к реплике.
К счастью, драйверы PostgreSQL предоставляют элегантное решение этой проблемы – параметр строки подключения target_session_attrs
. В версии PostgreSQL 14 были добавлены новые значения для target_session_attrs: read-only, primary, standby и prefer-standby. Этот параметр позволяет указать, какого типа сессию ожидает ваше приложение. Наиболее полезным значением для приложений, выполняющих операции чтения и записи, является read-write
. В этой статье мы подробно разберем, почему это так важно, продемонстрируем проблему на практике и покажем, как target_session_attrs=read-write
спасает ситуацию. Использование target_session_attrs=primary
, включая его специфические отличия от read-write
, будет подробно рассмотрено далее в статье.
Меня зовут Артём, я занимаюсь коммерческой разработкой с 2019 года. Последние несколько лет я активно использовал Spring Boot для создания backend-сервисов на Java и Kotlin.
Но в какой-то момент захотелось попробовать что-то новое. Не потому что Spring надоел, а просто чтобы выйти из зоны комфорта и узнать, как чувствует себя проект на другом языке. Я решил: возьму уже начатый pet-проект, перепишу его на Go — и посмотрю, как изменится подход, скорость разработки, ощущения.