Для работы с SQLite в Go нам потребуется драйвер go-sqlite3. Для использования драйвера вначале установим его, выполнив в командной строке/терминале следующую команду:
go get github.com/mattn/go-sqlite3
Пусть в папке со скриптом программы на Go у нас будет создана база данных SQLite, которая называется store.db, и в ней будет таблица products, которая описывается следующим скриптом:
CREATE TABLE products( id INTEGER PRIMARY KEY AUTOINCREMENT, model TEXT, company TEXT, price INTEGER );
Для открытия соединения с базой данных в функцию sql.Open() передается имя драйвера "sqlite3" и путь к файлу базы данных:
db, err := sql.Open("sqlite3", "store.db")
В результате установки подлючения метод db.Open возвратить объект *DB
, через который можно будет взаимодействовать в базой данных.
Для добавления используется метод Exec() объекта DB:
package main import ( "database/sql" "fmt" _ "github.com/mattn/go-sqlite3" ) func main() { db, err := sql.Open("sqlite3", "store.db") if err != nil { panic(err) } defer db.Close() result, err := db.Exec("insert into products (model, company, price) values ('iPhone X', $1, $2)", "Apple", 72000) if err != nil{ panic(err) } fmt.Println(result.LastInsertId()) // id последнего добавленного объекта fmt.Println(result.RowsAffected()) // количество добавленных строк }
Через дополнительные параметры метода db.Exec()
можно передавать значения выполняемому sql-выражению через
плейхолдеры $1, $2 и так далее, вместо которых вставляются значения дополнительных параметров метода db.Exec.
У результата операции есть метод result.LastInsertId()
, который возвращает id последнего добавленного объекта, и метод result.RowsAffected()
, который позволяет получить
количество добавленных строк:
Для получения данных применяется метод db.Query()
, который возвращает набор строк, либо db.QueryRow()
, который возвращает
одну строку:
package main import ( "database/sql" "fmt" _ "github.com/mattn/go-sqlite3" ) type product struct{ id int model string company string price int } func main() { db, err := sql.Open("sqlite3", "store.db") if err != nil { panic(err) } defer db.Close() rows, err := db.Query("select * from Products") if err != nil { panic(err) } defer rows.Close() products := []product{} for rows.Next(){ p := product{} err := rows.Scan(&p.id, &p.model, &p.company, &p.price) if err != nil{ fmt.Println(err) continue } products = append(products, p) } for _, p := range products{ fmt.Println(p.id, p.model, p.company, p.price) } }
Для работы с данными здесь определена структура product, которая соответствует данным в таблице Products.
Для получения данных вызывается метод Query():
rows, err := db.Query("select * from Products")
Этот метод в качестве параметра принимает sql-выражение SELECT на получение всех данных из таблицы Products. Результат выборки попадает в переменную rows, которая представляет указатель на структуру Rows. И с помощью метода rows.Next() мы можем последовательно перебрать все строки в полученном наборе:
for rows.Next(){ p := product{} err := rows.Scan(&p.id, &p.model, &p.company, &p.price) if err != nil{ fmt.Println(err) continue } products = append(products, p) }
Тип Rows определяет метод Scan, с помощью которого можно считать все полученные данные в переменные. Например, здесь считываем данные в структуру Product и затем добавляем ее в срез. Поскольку мы получаем все данные - все четыре столбца, то соответственно в Scan передается адреса четырех переменных.
После прочтения данных в срез мы можем делать с ними все что угодно, например, вывести на консоль:
В методе Query мы можем указывать дополнительные параметры. Например, получим товары, у которых цена больше 70000:
rows, err := db.Query("select * from Products where price > $1", 70000)
Если надо получить только одну строку, то можно использовать метод QueryRow():
row := db.QueryRow("select * from Products where id = $1", 2) prod := product{} err = row.Scan(&prod.id, &prod.model, &prod.company, &prod.price) if err != nil{ panic(err) } fmt.Println(prod.id, prod.model, prod.company, prod.price)
Для обновления данных применяется метод Exec:
package main import ( "database/sql" "fmt" _ "github.com/mattn/go-sqlite3" ) func main() { db, err := sql.Open("sqlite3", "store.db") if err != nil { panic(err) } defer db.Close() // обновляем строку с id=1 result, err := db.Exec("update Products set price = $1 where id = $2", 69000, 1) if err != nil{ panic(err) } fmt.Println(result.RowsAffected()) // количество обновленных строк }
Для удаления также применяется метод Exec:
package main import ( "database/sql" "fmt" _ "github.com/mattn/go-sqlite3" ) func main() { db, err := sql.Open("sqlite3", "store.db") if err != nil { panic(err) } defer db.Close() // удаляем строку с id=1 result, err := db.Exec("delete from Products where id = $1", 1) if err != nil{ panic(err) } fmt.Println(result.RowsAffected()) // количество удаленных строк }