Подключение к SQLite в Go: Полное руководство
Основные команды по управлению базой данных SQLite на языке программирования Go.
Categories:
Установка драйвера SQLite для Go
Перед началом работы установите драйвер SQLite:
go get github.com/mattn/go-sqlite3
Базовое подключение к базе данных
Простое подключение
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/mattn/go-sqlite3"
)
func main() {
// Открытие соединения с базой данных
db, err := sql.Open("sqlite3", "./test.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// Проверка соединения
err = db.Ping()
if err != nil {
log.Fatal(err)
}
fmt.Println("Successfully connected to SQLite database")
}
Подключение с параметрами
db, err := sql.Open("sqlite3", "file:test.db?cache=shared&mode=memory")
if err != nil {
log.Fatal(err)
}
Выполнение запросов
Создание таблицы
func createTable(db *sql.DB) error {
query := `
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`
_, err := db.Exec(query)
return err
}
Вставка данных
func insertUser(db *sql.DB, name, email string) (int64, error) {
res, err := db.Exec("INSERT INTO users(name, email) VALUES(?, ?)", name, email)
if err != nil {
return 0, err
}
return res.LastInsertId()
}
Выборка данных
type User struct {
ID int
Name string
Email string
CreatedAt string
}
func getUsers(db *sql.DB) ([]User, error) {
rows, err := db.Query("SELECT id, name, email, created_at FROM users")
if err != nil {
return nil, err
}
defer rows.Close()
var users []User
for rows.Next() {
var u User
err := rows.Scan(&u.ID, &u.Name, &u.Email, &u.CreatedAt)
if err != nil {
return nil, err
}
users = append(users, u)
}
return users, nil
}
Транзакции
func transferMoney(db *sql.DB, from, to int, amount float64) error {
tx, err := db.Begin()
if err != nil {
return err
}
// Откат транзакции при ошибке
defer func() {
if err != nil {
tx.Rollback()
}
}()
// Снимаем деньги с первого аккаунта
_, err = tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, from)
if err != nil {
return err
}
// Добавляем деньги на второй аккаунт
_, err = tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, to)
if err != nil {
return err
}
// Фиксируем транзакцию
return tx.Commit()
}
Подготовленные выражения (Prepared Statements)
func getUserByEmail(db *sql.DB, email string) (*User, error) {
stmt, err := db.Prepare("SELECT id, name, email FROM users WHERE email = ?")
if err != nil {
return nil, err
}
defer stmt.Close()
var u User
err = stmt.QueryRow(email).Scan(&u.ID, &u.Name, &u.Email)
if err != nil {
return nil, err
}
return &u, nil
}
Практические советы
- Пулинг соединений: SQLite не поддерживает множественные соединения на запись, но вы можете использовать пулинг для чтения:
db.SetMaxOpenConns(1) // Важно для SQLite
- Режим WAL: Для лучшей производительности:
_, err = db.Exec("PRAGMA journal_mode=WAL")
if err != nil {
log.Fatal(err)
}
- Обработка ошибок: Всегда проверяйте ошибки при закрытии ресурсов:
defer func() {
if err := rows.Close(); err != nil {
log.Printf("failed to close rows: %v", err)
}
}()
Полный пример приложения
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/mattn/go-sqlite3"
)
type User struct {
ID int
Name string
Email string
}
func main() {
// Подключение к базе данных
db, err := sql.Open("sqlite3", "./app.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// Настройка базы данных
if err := initDB(db); err != nil {
log.Fatal(err)
}
// Добавление пользователя
id, err := addUser(db, "John Doe", "john@example.com")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Added user with ID: %d\n", id)
// Получение списка пользователей
users, err := getUsers(db)
if err != nil {
log.Fatal(err)
}
fmt.Println("Users:")
for _, u := range users {
fmt.Printf("%d: %s (%s)\n", u.ID, u.Name, u.Email)
}
}
func initDB(db *sql.DB) error {
_, err := db.Exec(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE
)
`)
return err
}
func addUser(db *sql.DB, name, email string) (int64, error) {
res, err := db.Exec("INSERT INTO users(name, email) VALUES(?, ?)", name, email)
if err != nil {
return 0, err
}
return res.LastInsertId()
}
func getUsers(db *sql.DB) ([]User, error) {
rows, err := db.Query("SELECT id, name, email FROM users")
if err != nil {
return nil, err
}
defer rows.Close()
var users []User
for rows.Next() {
var u User
if err := rows.Scan(&u.ID, &u.Name, &u.Email); err != nil {
return nil, err
}
users = append(users, u)
}
return users, nil
}
Заключение
Работа с SQLite в Go проста и эффективна благодаря пакету database/sql
и драйверу go-sqlite3
. Основные принципы:
- Всегда закрывайте ресурсы (деферы для
Close()
) - Используйте подготовленные выражения для защиты от SQL-инъекций
- Для операций записи используйте транзакции
- Настраивайте параметры SQLite для оптимальной производительности