Открытие дескриптора базы данных

Пакет database/sql упрощает доступ к базе данных, снижая необходимость в управлении соединениями вручную. В отличие от многих API доступа к данным, в database/sql вы не открываете соединение явно, выполняете работу, а затем закрываете соединение. Вместо этого ваш код открывает дескриптор базы данных, представляющий пул соединений, а затем выполняет операции доступа к данным с использованием этого дескриптора, вызывая метод Close только тогда, когда необходимо освободить ресурсы, такие как те, что удерживаются полученными строками или подготовленной инструкцией.

Иными словами, это дескриптор базы данных, представленный через sql.DB, управляет соединениями, открывая и закрывая их от имени вашего кода. По мере того как ваш код использует дескриптор для выполнения операций с базой данных, эти операции получают одновременный доступ к базе данных. Подробнее см. Управление соединениями.

Примечание: Также можно зарезервировать соединение с базой данных. Подробнее см. Использование выделенных соединений.

Помимо API, доступных в пакете database/sql, сообщество Go разработало драйверы для всех наиболее распространённых (и многих менее распространённых) систем управления базами данных (СУБД).

При открытии дескриптора базы данных вы выполняете следующие высокоуровневые шаги:

  1. Найдите драйвер.

    Драйвер переводит запросы и ответы между вашим Go-кодом и базой данных. Подробнее см. Поиск и импорт драйвера базы данных.

  2. Откройте дескриптор базы данных.

    После того как вы импортировали драйвер, можно открыть дескриптор для конкретной базы данных. Подробнее см. Открытие дескриптора базы данных.

  3. Подтвердите соединение.

    После открытия дескриптора базы данных ваш код может проверить, доступно ли соединение. Подробнее см. Подтверждение соединения.

Ваш код обычно не открывает или не закрывает соединения с базой данных вручную — это делается дескриптором базы данных. Однако ваш код должен освобождать ресурсы, которые он получает по пути, например, sql.Rows, содержащий результаты запроса. Подробнее см. Освобождение ресурсов.

Поиск и импорт драйвера базы данных

Для работы с базой данных вам понадобится драйвер, поддерживающий используемую вами СУБД. Чтобы найти драйвер для вашей базы данных, см. SQLDrivers.

Чтобы сделать драйвер доступным для вашего кода, вы импортируете его так же, как и другой пакет Go. Вот пример:

<code>import "github.com/go-sql-driver/mysql"
</code>

Обратите внимание, что если вы не вызываете функции напрямую из пакета драйвера – например, когда он используется неявно пакетом sql – вам потребуется использовать пустой импорт, который добавляет подчеркивание перед путём импорта:

<code>import _ "github.com/go-sql-driver/mysql"
</code>

Примечание: В качестве лучшей практики рекомендуется избегать использования собственного API драйвера для операций с базой данных. Вместо этого используйте функции из пакета database/sql. Это поможет сделать ваш код слабо связанным с СУБД, что облегчит возможность переключения на другую СУБД в случае необходимости.

Открытие дескриптора базы данных

Дескриптор базы данных sql.DB предоставляет возможность читать из базы данных и записывать в неё, как по отдельности, так и в рамках транзакции.

Вы можете получить дескриптор базы данных, вызвав либо sql.Open (который принимает строку подключения), либо sql.OpenDB (который принимает driver.Connector). Оба возвращают указатель на sql.DB.

Примечание: Обязательно храните учетные данные базы данных вне исходного кода Go. За дополнительной информацией обращайтесь к разделу Хранение учетных данных базы данных.

Открытие с использованием строки подключения

Используйте функцию sql.Open, когда вы хотите подключиться с использованием строки подключения. Формат строки будет зависеть от используемого вами драйвера.

Вот пример для MySQL:

<code>db, err = sql.Open("mysql", "username:password@tcp(127.0.0.1:3306)/jazzrecords")
if err != nil {
  log.Fatal(err)
}
</code>

Однако вы, вероятно, обнаружите, что хранить свойства подключения в более структурированном виде делает код более читаемым. Подробности зависят от драйвера.

Например, вы можете заменить предыдущий пример следующим, который использует Config драйвера MySQL для указания свойств и его метод FormatDSN для построения строки подключения.

<code>// Укажите свойства подключения.
cfg := mysql.NewConfig()
cfg.User = username
cfg.Passwd = password
cfg.Net = "tcp"
cfg.Addr = "127.0.0.1:3306"
cfg.DBName = "jazzrecords"
// Получите дескриптор базы данных.
db, err = sql.Open("mysql", cfg.FormatDSN())
if err != nil {
  log.Fatal(err)
}
</code>

Открытие с использованием коннектора

Используйте sql.OpenDB функцию, когда вы хотите воспользоваться особенностями подключения, которые недоступны в строке подключения. Каждый драйвер поддерживает свой набор свойств подключения, часто предоставляя способы настройки запроса подключения, специфичного для СУБД.

Адаптируя предыдущий пример с использованием sql.Open для использования sql.OpenDB, можно создать дескриптор с помощью следующего кода:

<code>// Укажите свойства подключения.
cfg := mysql.NewConfig()
cfg.User = username
cfg.Passwd = password
cfg.Net = "tcp"
cfg.Addr = "127.0.0.1:3306"
cfg.DBName = "jazzrecords"
// Получите драйвер-специфичный коннектор.
connector, err := mysql.NewConnector(&cfg)
if err != nil {
  log.Fatal(err)
}
// Получите дескриптор базы данных.
db = sql.OpenDB(connector)
</code>

Обработка ошибок

Ваш код должен проверять наличие ошибки при попытке создания дескриптора, например, с помощью sql.Open. Это не будет ошибкой соединения. Вместо этого вы получите ошибку, если sql.Open не смог инициализировать дескриптор. Это может произойти, например, если он не может разобрать указанный вами DSN.

Подтверждение подключения

Когда вы открываете дескриптор базы данных, пакет sql может не создавать новое подключение к базе данных сразу. Вместо этого он может создать подключение тогда, когда это потребуется вашему коду. Если вы не собираетесь использовать базу данных немедленно и хотите подтвердить, что подключение может быть установлено, вызовите Ping или PingContext.

Код в следующем примере отправляет пинг базе данных для подтверждения подключения.

<code>db, err = sql.Open("mysql", connString)
// Подтвердите успешное подключение.
if err := db.Ping(); err != nil {
  log.Fatal(err)
}
</code>

Хранение учетных данных базы данных

Избегайте хранения учетных данных базы данных в исходном коде на Go, так как это может раскрыть содержимое вашей базы данных другим. Вместо этого найдите способ хранить их в месте вне вашего кода, но доступном для него. Например, рассмотрите приложение для хранения секретов, которое хранит учетные данные и предоставляет API, который ваш код может использовать для получения учетных данных для аутентификации с вашей СУБД.

Один из популярных подходов — хранить секреты в переменных окружения перед запуском программы, возможно, загружаемые из менеджера секретов, а затем ваша программа на Go может читать их с помощью os.Getenv:

<code>username := os.Getenv("DB_USER")
password := os.Getenv("DB_PASS")
</code>

Этот подход также позволяет вам самостоятельно устанавливать переменные окружения для локального тестирования.

Освобождение ресурсов

Несмотря на то, что вы не управляете подключениями или не закрываете их явно с помощью пакета database/sql, ваш код должен освобождать полученные ресурсы, когда они больше не требуются. К таким ресурсам могут относиться ресурсы, удерживаемые sql.Rows, представляющими данные, возвращённые запросом, или sql.Stmt, представляющим подготовленную инструкцию.

Обычно ресурсы закрываются с помощью отложенного вызова функции Close, чтобы ресурсы были освобождены до выхода из содержащей функции.

В следующем примере кода откладывается вызов Close для освобождения ресурса, удерживаемого sql.Rows.

<code>rows, err := db.Query("SELECT * FROM album WHERE artist = ?", artist)
if err != nil {
  log.Fatal(err)
}
defer rows.Close()
// Loop through returned rows.
</code>
GoRu.dev Golang на русском

На сайте представлена адаптированная под русский язык документация языка программирования Golang