MySQL
MySQL — самая популярная открытая реляционная база данных. Конкретные знания SQL здесь не будут подробно рассматриваться. Если вы не знакомы с SQL, пожалуйста, изучите его самостоятельно. В этой статье просто объясняется, как выполнять SQL-операции на Go. В проектах обычно не используют драйвер напрямую для операций с базой данных, а применяют ORM-фреймворки. Здесь используется библиотека sqlx, которая расширяет стандартную библиотеку sql. Она не такая богатая функциями, как ORM, но выигрывает в простоте. Если вы хотите использовать ORM, можете ознакомиться с библиотеками Gorm, Xorm, Ent.
Зависимости
Загрузка библиотеки sqlx:
$ go get github.com/jmoiron/sqlxsqlx и стандартная библиотека database/sql поддерживают не только MySQL, но и любые базы данных, реализующие интерфейс driver.Driver, например:
- PostgreSQL
- Oracle
- MariaDB
- SQLite
- и другие реляционные базы данных
Для использования соответствующей базы данных необходимо реализовать драйвер базы данных. Драйвер может быть написан вами самостоятельно или быть сторонней библиотекой. Перед использованием необходимо зарегистрировать драйвер с помощью sql.Register, и только затем его можно использовать. Однако обычно загружаемые библиотеки драйверов автоматически регистрируют драйвер, и вам не нужно регистрировать его вручную.
func Register(name string, driver driver.Driver)Поскольку MySQL довольно популярен и прост, в этой статье используется MySQL для объяснения. Операции с другими реляционными базами данных практически не отличаются. Загрузка драйвера MySQL:
$ go get github.com/go-sql-driver/mysqlПодключение к базе данных
С помощью функции sqlx.Open можно открыть соединение с базой данных. Она принимает два параметра: первый — имя драйвера, второй — источник данных (обычно называемый DSN).
func Open(driverName, dataSourceName string) (*DB, error)Имя драйвера — это имя, используемое при регистрации драйвера, должно совпадать. DSN — это адрес подключения к базе данных, который может отличаться для каждой базы данных. Для MySQL он выглядит следующим образом:
db, err := sqlx.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test")Подготовка данных
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`age` tinyint(0) NULL DEFAULT NULL,
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('12132', '张三', 35, '北京市');
INSERT INTO `user` VALUES ('16162', '王五', 22, '上海市');
SET FOREIGN_KEY_CHECKS = 1;Запрос
Запрос данных и отображение результатов на структуру:
var db *sqlx.DB
type Person struct {
UserId string `db:"id"`
Username string `db:"name"`
Age int `db:"age"`
Address string `db:"address"`
}
func init() {
conn, err := sqlx.Open("mysql", "root:wyh246859@tcp(127.0.0.1:3306)/test")
if err != nil {
fmt.Println("Open mysql failed", err)
return
}
db = conn
}
func main() {
query()
defer db.Close()
}
func query() {
var person Person
// Get для одного, Select для нескольких
err := db.Get(&person, "select * from user where id = ?", "12132")
if err != nil {
fmt.Println("query failed:", err)
return
}
fmt.Printf("query succ:%+v", person)
}
func list() {
var persons []Person
err := db.Select(&persons, "select * from user")
if err != nil {
fmt.Println("list err", err)
return
}
fmt.Printf("list succ,%+v", persons)
}Вставка
Вставка данных:
func insert() {
result, err := db.Exec("insert into user value (?,?,?,?)", "120230", "李四", 12, "广州市")
if err != nil {
fmt.Println("insert err:", err)
return
}
id, err := result.LastInsertId()
if err != nil {
fmt.Println("insert err:", err)
return
}
fmt.Println("insert succ:", id)
}Обновление
Обновление данных:
func update() {
res, err := db.Exec("update user set name = ? where id = ?", "赵六", "120230")
if err != nil {
fmt.Println("update err:", err)
return
}
eff, err := res.RowsAffected()
if err != nil || eff == 0 {
fmt.Println("update err:", err)
return
}
fmt.Println("Update succ")
}Удаление
Удаление данных:
func delete() {
res, err := db.Exec("delete from user where id = ?", "120230")
if err != nil {
fmt.Println("delete err:", err)
return
}
eff, err := res.RowsAffected()
if err != nil || eff == 0 {
fmt.Println("delete err:", err)
return
}
fmt.Println("delete succ")
}Транзакции
func (db *DB) Begin() (*Tx, error) // Начало транзакции
func (tx *Tx) Commit() error // Фиксация транзакции
func (tx *Tx) Rollback() error // Откат транзакцииПосле начала транзакции обычно добавляют defer tx.Rollback() для безопасности. Если в процессе возникает ошибка, происходит откат. Если транзакция успешно зафиксирована, откат становится недействительным.
func main() {
transation, err := db.Begin()
if err != nil {
fmt.Println("transation err")
}
defer transation.Rollback()
insert()
query()
update()
query()
delete()
transation.Commit()
}