Ответ
Да, я работал с вызовом хранимых процедур из Go. Для этого используется стандартный пакет database/sql
.
Основной способ вызова зависит от того, возвращает ли процедура результат или нет.
1. Вызов процедуры без возврата строк (например, для изменения данных):
Используется метод Exec
. Синтаксис вызова (CALL
или EXEC
) зависит от конкретной СУБД.
Пример для PostgreSQL:
// Процедура: CREATE PROCEDURE update_user_balance(user_id INT, amount DECIMAL) ...
_, err := db.Exec("CALL update_user_balance($1, $2)", 123, 50.00)
2. Вызов функции с возвратом результата:
Используются методы QueryRow
( для одной строки) или Query
(для нескольких строк).
Пример для PostgreSQL:
// Функция: CREATE FUNCTION get_user_balance(user_id INT) RETURNS DECIMAL ...
var balance float64
err := db.QueryRow("SELECT get_user_balance($1)", 123).Scan(&balance)
Когда использование хранимых процедур оправдано:
- Производительность: Для выполнения сложных, многоэтапных операций с данными. План запроса кэшируется на стороне СУБД, и уменьшается сетевой трафик между приложением и базой.
- Безопасность: Можно выдать приложению права только на вызов определенных процедур, а не на прямой доступ к таблицам.
- Работа с легаси-системами: Когда бизнес-логика уже реализована в базе данных и ее перенос в приложение нецелесообразен.
Основные недостатки:
- Скрытие бизнес-логики: Логика оказывается в "черном ящике" базы данных, ее сложнее версионировать вместе с кодом приложения (хотя можно использовать миграции).
- Сложность тестирования: Тестировать логику внутри БД сложнее, чем код на Go.
- Зависимость от СУБД (Vendor Lock-in): Синтаксис процедур сильно привязан к конкретной СУБД.
В большинстве современных Go-проектов предпочитают реализовывать бизнес-логику в самом приложении, используя ORM (GORM) или query builder (sqlc, sqlx) для более прозрачной и поддерживаемой работы с данными.