В этой статье хочу обобщить проблемы работы с базами данных под управлением golang. При решении простых задач обычно эти проблемы не видны. С ростом проекта масштабируются и проблемы. Наиболее злободневные из них: Статья построена на основании пакета github.com/adverax/echo/database/sql. Семантика использования этого пакета максимально приближена к стандартному пакету database/sql, поэтому не думаю, что при его использовании у кого-нибудь возникнут проблемы. Как правило, крупные системы стараются делать слабо связными с четкой зоной ответственности каждого компонента системы. Поэтому широко практикуются паттерны проектирования типа издатель/подписчик. Рассмотрим необольшой пример по регистрации нового пользователя в системе.  В этом примере нас прежде всего интересует событие OnSignup. Для упрощения, обработчик представлен единственной функцией (в реальной жизни все сложнее). В сигнатуре события мы жестко прописываем тип первого параметра, что обычно имеет далекоидущие последтсвия.
Предположим, что теперь мы хотим расширить функционал нашего приложения и в случае успешной регистрации пользователя отправлять сообщение ему в личный кабинет. В идеале, сообщение должно помещаться в той же транзакции, что и регистрация пользователя. Как видно из примера, мы вынуждены были изменить сигнатуру события. Такое решение не является чистым и подразумевает, что обработчики обладают знаниями о контексте исполнения запроса к базе данных. Значительно более чистым решением было бы использовать обобщенный интерфейс базы данных и транзакции — область видимости.  Для реализации этого подхода нам понадобится поддержка вложенных транзакций, поскольку обработчик в свою очередь может задействовать транзакции. К счастью, это не является проблемой, поскольку большинство СУБД поддерживает механизм SAVEPOINT. При обычной практике, соединение с базой данных не передается в виде параметра, как было показано выше, а каждый менеджер хранит у себя ссылку на соединение с базой. Это позволяет упростить сигнатуры методов и повысить читаемость кода. В нашем же случае избежать этого невозможно, поскольку требуется передавать ссылку на транзакцию.
Достаточно изящное решение заключается в том, чтобы поместить ссылку на транзакцию (область видимости) в контекст, ведь контекст позиционируется, как сквозной параметр. Тогда мы сможем еще упростить наш код: Из этого примера видно, что мы сохранили полную изоляцию менеджеров, повысили читаемость кода и добились их совместной работы в единой области видимости. Библиотека также поддерживает использование репликаций. Все запросы типа Exec направляются на Master. Запросы же типа Slave передаются на случаным образом выбранный Slave. Для поддержки репликации достаточно указать несколько источников данных: В случае использования единственного источника данных при открытии базы данных, она будет открыта в обычном режиме без дополнительного оверхеда. Как известно, метрики дешевы, а логи дороги. Поэтому было решено добавить поддержку метрик по умолчанию. Очень часть необходимо во время отладки протоколировать запросы к базе данных. Однако, мне не встречался качественный механизм протоколирования с нулевым оверхедом в продакшене. Библиотека позволяет элегантно решить эту проблему за счет обертки базы данных. Для профилирования базы данных достаточно передать ей соответствующий активатор: Предлагаемый пакет позволяет расширить возможности взаимодействия с базой данных, при этом скрыв излишние детали. Это позволяет улучшить качество кода, оставляя его слабозвязным и прозрачным, несмотря на рост сложности приложения.