Go Mysql驱动
Golang中MYSQL驱动
- Mysql库https://github.com/go-sql-driver/mysql
- Go本身不提供具体数据库驱动,只提供驱动接口和管理。
- 各个数据库驱动需要第三方实现,并且注册到Go中的驱动管理中。
安装golang mysql drvier
go get github.com/go-sql-driver/mysql
代码中需要注册mysql数据库驱动,通过引入空白导入mysql包来完成。
为什么需要使用空白导入? 是因为需要执行mysql包的初始化代码(代码位于%GOPATH%/github.com/go-sql-driver/mysql/driver.go)
func init() {
sql.Register("mysql", &MySQLDriver{})
}
连接数据的DSN格式
username:password@protocol(address)/dbname?param=value
Prepared Statement
sql.Stmt支持预备表达式,可以用来优化SQL查询提高性能,减少SQL注入的风险, DB.Prepare()和Tx.Prepare()都提供了对于预备表达式的支持。
预处理的流程:
step1. 将sql分为2部分.命令部分和数据部分.
step2. 首先将命令部分发送给mysql服务器,mysql进行预处理.(如生成AST)
step3. 然后将数据部分发送给mysql服务器,mysql进行占位符替换.
step4. mysql服务器执行sql语句,把执行结果发送给客户端.
预处理的优势:
1.因为发送命令后,在mysql服务器端,就会将AST生成好,所以不需要对每一次值的更换都重新生成一次AST.对同样的数据不同的SQL来讲,只需生成1次AST,并缓存起来即可.
2.避免SQL注入.因为mysql知道再次发送过来的内容为”数据”,因此不会将这些数据解析为SQL,避免了SQL注入.
需要注意的点:
使用预处理进行查询操作时,不仅在defer时需要关闭结果集,而且还要关闭命令句柄,否则同样会占用连接,导致阻塞.
package main import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
) type User struct {
Id int `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
} func PrepareQuery(db *sql.DB, id int) {
stmt, err := db.Prepare("select id, name, age from user where id>?")
if err != nil {
panic(err)
} rows, err := stmt.Query(id)
if err != nil {
panic(err)
} defer stmt.Close()
defer rows.Close() for rows.Next(){
var user User
err := rows.Scan(&user.Id, &user.Name, &user.Age)
if err != nil {
panic(err)
}
fmt.Printf("user: %#v\n", user)
}
} func main() { dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
} defer db.Close() PrepareQuery(db, ) }
Mysql创建表:
CREATE TABLE user (
id int(20) NOT NULL AUTO_INCREMENT,
name varchar(20) DEFAULT '',
age int(2) DEFAULT '0',
PRIMARY KEY (id))
ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
数据库增删改查
insert
package main import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
) func Insert(db *sql.DB) {
name := "Vincent"
age := result, err := db.Exec("insert into user(name, age) values (?,?)", name, age)
if err != nil {
panic(err)
} id, err := result.LastInsertId()
if err != nil {
panic(err)
} affected, err := result.RowsAffected()
if err != nil {
panic(err)
} fmt.Printf("last insert id:%d affect rows:%d\n", id, affected)
} func main() {
dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("connect to db success!!!")
Insert(db)
}
delete
package main import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
) func Delete(db *sql.DB, id int) {
result, err := db.Exec("delete from user where id=?", id)
if err != nil {
panic(err)
} rowsAffected, err := result.RowsAffected()
if err != nil {
panic(err)
}
fmt.Printf("delect id:%d, affect rows:%d\n", id, rowsAffected)
} func main() {
dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, _ := sql.Open("mysql", dns)
Delete(db, )
}
update
package main import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
) func Update(db *sql.DB) {
name := "Miles"
age :=
id := result, err := db.Exec("update user set name=?, age=? where id=?", name, age, id)
if err != nil {
panic(err)
} // RowsAffected returns the number of rows affected by an
// update, insert, or delete.
rowsAffected, err := result.RowsAffected()
if err != nil {
panic(err)
} fmt.Printf("update id:%d, affect rows:%d\n", id, rowsAffected) } func main() {
dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
}
fmt.Println("connect to db success!!!")
Update(db)
}
query
package main import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
"log"
) type User struct {
Id int `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
} // 单行查询,如果查询到多个结果,只返回第一行,查询不到结果就ErrNoRows错误。
func QueryRow(db *sql.DB) {
id:=
row := db.QueryRow("select id, name, age from user where id=?", id) var user User
err := row.Scan(&user.Id, &user.Name, &user.Age) if err == sql.ErrNoRows {
log.Printf("not found data of the id:%d",id)
} if err != nil {
panic(err)
} fmt.Printf("user: %#v\n", user)
} // 多行查询, 查询不到任何记录也不会报错。
func Query(db *sql.DB) {
id :=
rows, err := db.Query("select id, name, age from user where id>?", id)
if err != nil {
panic(err)
}
if err == sql.ErrNoRows {
log.Printf("not found data of id:%d\n", id)
return
}
defer rows.Close() for rows.Next() {
var user User
err := rows.Scan(&user.Id, &user.Name, &user.Age)
if err != nil {
panic(err)
}
fmt.Printf("user: %#v\n", user)
} } func main() {
dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
} fmt.Printf("connect to db success\n") //QueryRow(db) Query(db)
}
事务支持
事务(transaction)
- transaction, err := Db.Begin() 开启事务
- transaction.Exec() 执行事务
- transaction.Commit() 提交事务
- transaction.Rollback() 回滚事务
A. 事务的应用场景
1. 同时更新多个表
2. 同时更新多行数据
B. 事务的ACID
1. 原子性
2. 一致性
3. 隔离性
4. 持久性
需要注意的点:
1. 执行失败要回滚
2. 提交失败要回滚
package main import (
_ "github.com/go-sql-driver/mysql"
"database/sql"
"fmt"
) func Transaction(db *sql.DB) { // 开启事务
tx, err := db.Begin() if err != nil {
panic(err)
} result, err := tx.Exec("insert into user(name, age)values(?,?)", "Jack", )
if err != nil {
// 失败回滚
tx.Rollback()
panic(err)
} fmt.Println("result", result) exec, err := tx.Exec("update user set name=?, age=? where id=?", "Jack", , )
if err != nil {
// 失败回滚
tx.Rollback()
panic(err)
}
fmt.Println("exec", exec) // 提交事务
err = tx.Commit() if err != nil {
// 失败回滚
tx.Rollback()
panic(err)
}
} func main() { dns := "root:123456@tcp(172.16.65.200:3306)/golang"
db, err := sql.Open("mysql", dns)
if err != nil {
panic(err)
} err = db.Ping()
if err != nil {
panic(err)
} Transaction(db)
}
Mysql日期时间类型报错
sql: Scan error on column index 1: unsupported Scan, storing driver.Value type []uint8 into type *time.Time
原因是在调用sql.Open()时没有将parseTime设置为True。加入parseTime即可修复问题:
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname?parseTime=true")
Go Mysql驱动的更多相关文章
- python 3.5.2安装mysql驱动报错
python 3.5.2安装mysql驱动报错 python 3.5.2安装mysql驱动时出现如下异常: [root@localhost www]# pip install mysql-connec ...
- Go-MySQL-Driver:一个Go语言的轻量级极速的mysql驱动
Go语言的 database/sql 包的一个 MySQL驱动. 特性 轻量级与快速 原生Go语言,没有C绑定,只有纯Go 没有不安全的操作(类型转换等) 动态处理崩溃的连接 动态连接池 支持大于16 ...
- Ubuntu 16.04 - python3 安装mysql驱动
阿西吧,今天碰到一件特别蛋疼的事,给Ubuntu安装Python的MySQL驱动,驱动显示安装成功了 pip install mysql-connector 但是 在程序中导入,老是报错. Trace ...
- QT编译mysql驱动
一. 下载mysql C链接库 地址:http://dev.mysql.com/downloads/ 根据当前系统选择下载: 二. 安装下载好的mysql驱动文件 注意,一定要安装在不含有中文.空格以 ...
- centos7下编译qt的mysql驱动
在编译mysql驱动之前,首先要安装mysql,可以使用yum安装,这里将不再介绍. 在将qt和mysql都安装好之后,首先找到mysql的头文件以及他的共享库,我的mysql是使用yum安装的,头文 ...
- MySQL驱动阅读------Connection连接的建立,基于JDBC-----5.1.26
一般获取数据库连接的程序 Class.forName("com.mysql.jdbc.Driver"); final Connection connection = (Connec ...
- java mysql驱动
mysql驱动方式有三种, 1.第一种是先把jar包放在项目的目录下,通过添加jar包,是使用相对地址的,这样把项目复制到其它电脑也可以用 2.第二种方法是导入外部的jar包,是绝对地址,如果项目要复 ...
- Window下 Qt 编译MySQL驱动(居然用到了动态库格式转换工具)
一步步在Window下开发Qt 今天开始安装MySQL,看了些关于MySQL安装的博文,方法大致相同,但是遇到的细节问题各有不同,或者没有讲全面,下面来说说个人的安装过程及遇到的问题. 1.首先下载, ...
- Oozie安装时放置Mysql驱动包的总结(网上最全)
不多说,直接上干货! 对于在oozie里放置Mysql驱动包的总结 根据网上的参考以及我个人经验安装的使用 (1)放一份到$OOZIE_HOME/libext下 (是 mysql-connector- ...
- 关于mysql驱动包的in语句的bug
今天发现一个MySQL驱动包执行in语句的一个bug,也许会有很多人还不知道,那么跟大家分享一下. 驱动包版本:mysql-connector-java-5.1.36.jar 在使用dbutils执行 ...
随机推荐
- 1. 写出一个能创建多级目录的 PHP 函数(新浪网技术部)
function create_dir($path,$mode){ if (is_dir($path)){ echo "该目录已经存在"; }else{ if(mkdir($pat ...
- awk合并两个文件并显示
问题: 答案:
- [JAVA · 0基础]:19.容器类
概述 容器 就是存放数据的一个集合 (java提供了一个接口专门去约束我们容器的实现类) watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L ...
- X明X源面试题《一》
本文转载自zhangkang 今天去明源面试,面试题目如下 1 有两张表 A 学生表 ID Name age 1 李1 ...
- coursera 《现代操作系统》 -- 第七周 存储模型(1)
虚拟地址 隔离进程,便于管理. 问:为什么不直接划分物理地址为一块一块,直接管理,而要做一层虚拟地址的映射呢? 栈和堆 Differences between Stack and Heap Stack ...
- Socket_leaks open socket #5024 left in connection
open socket left in connection http://mailman.nginx.org/pipermail/nginx/2012-September/035627.html D ...
- <2013 08 26> 雅思听力相关
近两日开始接触雅思题型,初步做了6套剑桥雅思题的听力部分,完成情况还可以,这里做个总结. 1.听力总共约40左右道题目,30min左右完成,结束后有十分钟把答案写到答题卷上.所有听力材料都只播放一遍! ...
- MySQL中事务的概述ACID了解
事务可由一条非常简单的SQL语句组成,也可以有一组复杂的SQL语句组成.事务是访问并更新数据库中各种数据项的一个程序执行单元.在事务中操作,要么都做修改,要么都不做,这就是事务的目的,也是事务模型区别 ...
- MySQL 5.6 死锁演示 及 日志分析
1. 表结构 CREATE TABLE dead_update ( a ) ', PRIMARY KEY (a) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ; ), ...
- 测试百度地图输入GPS经纬度显示位置API
1.我的GPS获取的经纬度做度分秒转换后为 34.636055,112.40832 2.百度API介绍 GPS的坐标是WGS84,所以测试API http://api.map.baidu.com/ge ...