Для работы с MySQL будем использовать драйвер Go MySQL Driver. Прежде всего нам надо добавить данный драйвер к переменной $GOPATH. Для этого выполним в командной строке/терминале следующую команду:
go get github.com/go-sql-driver/mysql
Вначале создадим на сервере MySQL базу данных productdb и в ней таблицу products. Для этого можно использовать следующие выражений SQL
create database productdb; use productdb; create table products ( id int auto_increment primary key, model varchar(30) not null, company varchar(30) not null, price int not null )
То есть база данных productdb, в ней есть таблица products, которая будет хранить информацию о товарах, будет 4 столбца: id - идентификатор каждой записи, model - название товара, company - производитель товара и price - цена товара.
Созданная база данных пуста, поэтому добавим в нее какие-нибудь данные:
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "root:password@/productdb") if err != nil { panic(err) } defer db.Close() result, err := db.Exec("insert into productdb.Products (model, company, price) values (?, ?, ?)", "iPhone X", "Apple", 72000) if err != nil{ panic(err) } fmt.Println(result.LastInsertId()) // id добавленного объекта fmt.Println(result.RowsAffected()) // количество затронутых строк }
Вначале подключаем все нужные нам пакеты. Для работы с реляционной базой данных необходим пакет "database/sql". И так как мы используем mysql, то также подключаем пакет "github.com/go-sql-driver/mysql", причем обратите внимание, что перед ним стоит знак подчеркивания. Этот знак позволяет при загрузке пакета инициализировать его с помощью вызова функции init.
Далее открываем подключение функцией Open:
sql.Open("mysql", "root:password@/productdb")
Первый аргумент функции - название драйвера, в данном случае это "mysql". Второй параметр имеет форму "логин:пароль@/база_данных". Логин и пароль должны быть те, которые были указаны для mysql при его установке. В моем случае логин - root, а пароль - password. Название базы данных -productdb - та, которая была создана выше.
Эта функция возвращает объект базы данных - DB. И для добавления данных у этого объекта вызывается метод Exec():
result, err := db.Exec("insert into productdb.Products (model, company, price) values (?, ?, ?)", "iPhone X", "Apple", 72000)
Первый аргумент функции - это sql-выражение, которое добавляет строку в таблицу Products. Знаки вопроса в этом выражении представляют плейсхолдеры, вместо которых вставляются значения, которые передаются через второй, третий и последующие параметры. То есть в таблице Products четыре столбца, но один из них автогенерируемый - id. Поэтому передаем три значения - для столбцов model, company и price. Поэтому в выражении три знака вопроса и соответственно функция принимает три дополнительных параметра. Все дополнительные параметры передаются в sql-выражение на место плейсхолдеров по позиции - первый параметр вместо первого плейсхолдера и так далее.
Результат выполнения функции попадает в переменную result, которая хранит результат выполнения операции в базе данных. В частности, через метод result.LastInsertId() мы можем получить id последнего добавленного объекта, а с помощью метода result.RowsAffected() - количество добавленных строк.
И при выполнении данного скрипта получим следующие результаты:
При этом необязательно определять все добавляемые данные через параметры, можно ввести их напрямую в sql-выражение:
result, err := db.Exec("insert into productdb.Products (model, company, price) values ('Pixel 2', 'Google', 64000)")
Теперь получим ранее добавленные данные:
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) type product struct{ id int model string company string price int } func main() { db, err := sql.Open("mysql", "root:password@/productdb") if err != nil { panic(err) } defer db.Close() rows, err := db.Query("select * from productdb.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 productdb.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 productdb.Products where price > ?", 70000)
Если надо получить только одну строку, то можно использовать метод QueryRow():
row := db.QueryRow("select * from productdb.Products where id = ?", 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/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "root:password@/productdb") if err != nil { panic(err) } defer db.Close() // обновляем строку с id=1 result, err := db.Exec("update productdb.Products set price = ? where id = ?", 69000, 1) if err != nil{ panic(err) } fmt.Println(result.LastInsertId()) fmt.Println(result.RowsAffected()) }
Для удаления также применяется метод Exec:
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "root:password@/productdb") if err != nil { panic(err) } defer db.Close() result, err := db.Exec("delete from productdb.Products where id = 1") if err != nil{ panic(err) } fmt.Println(result.LastInsertId()) // id последнего удаленого объекта fmt.Println(result.RowsAffected()) // количество затронутых строк }