博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
go 数据库操作
阅读量:2339 次
发布时间:2019-05-10

本文共 4804 字,大约阅读时间需要 16 分钟。

Golang支持DB操作位于database包下,支持基本CRUD操作、事务和Prepared Statement,本文以MySQL为例。

MySQL驱动安装 
使用数据库之前,必须安装相关MySQL数据驱动,如果未安装驱动或者没有引入驱动库会报以下错误: 
failed to open database: sql: unknown driver "mysql" (forgotten import?) 
安装golang mysql driver 
go get github.com/go-sql-driver/mysql 
代码中还需注册数据库驱动,通过引入空白倒入mysql包来完成

import( 
"database/sql"
// 引入数据库驱动注册及初始化
_ "github.com/go-sql-driver/mysql" )

这段空白倒入代码实际执行mysql包的初始化代码,位于%GOPATH%/github.com/go-sql-driver/mysql/driver.go

func init() {
sql.Register("mysql", &MySQLDriver{})
}

准备测试数据 
连接MySQL 
mysql -uroot -p 
选择数据库test 
use test 
创建测试用的users表和order表,并插入测试数据

#创建user表 
DROP TABLE IF EXISTS `order`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE IF NOT EXISTS `user` (`uid` SERIAL PRIMARY KEY, `name` VARCHAR(20) NOT NULL, `password` VARCHAR(20) NOT NULL) ENGINE=`innodb`, CHARACTER SET=utf8;
#创建order表
CREATE TABLE IF NOT EXISTS `order`(`oid` SERIAL PRIMARY KEY, `uid` BIGINT(20) UNSIGNED NOT NULL, `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`uid`) REFERENCES `user`(`uid`))ENGINE=innodb,CHARACTER SET=utf8;
#插入测试数据
INSERT INTO `user`(`name`,`password`) VALUES('nick', 'nick'),('jacky', 'jacky');
INSERT INTO `order`(`uid`) VALUES(1),(2);

连接数据库 
连接数据的DSN格式为: 
username:password@protocol(address)/dbname?param=value 
示例代码:

db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test?charset=utf8") 
if err != nil {
fmt.Println("failed to open database:", err.Error())
return
}
defer db.Close()

返回的DB对象,实际封装了一个数据库连接池,对于goroutine是线程安全的,可以放心使用。这个数据库连接池由"database/sql"包负责自动创建和回收。连接池的大小可以由SetMaxIdleConns指定。 
需要注意的是,创建DB对象成功,并不代表已经成功的连接了数据库,数据库连接只有在真正需要的时候才会被创建。因此如果,在创建DB对象后想验证数据库连接是否有效,可以调用Ping()或者通过

关闭数据库

defer db.Close()

关闭数据库并释放全部已打开的资源。实际上,很少需要进行关闭操作,DB对象实际上长期存活并在所有的goroutine之间共享

CRUD 
DB中执行SQL通过Exec和Query方法,查询操作是通过Query完成,它会返回一个sql.Rows的结果集,包含一个游标用来遍历查询结果;Exec方法返回的是sql.Result对象,用于检测操作结果,及被影响记录数

查询

// 获取USERS表中的前十行记录 
rows, err := db.Query("SELECT * FROM user")
if err != nil {
fmt.Println("fetech data failed:", err.Error())
return
}
defer rows.Close()
for rows.Next() {
var uid int
var name, password string
rows.Scan(&uid, &name, &password)
fmt.Println("uid:", uid, "name:", name, "password:", password)
}

插入

// 插入一条新数据 
result, err := db.Exec("INSERT INTO `user`(`name`,`password`) VALUES('tom', 'tom')")
if err != nil {
fmt.Println("insert data failed:", err.Error())
return
}
id, err := result.LastInsertId()
if err != nil {
fmt.Println("fetch last insert id failed:", err.Error())
return
}
fmt.Println("insert new record", id)

更新

// 更新一条数据 
result, err = db.Exec("UPDATE `user` SET `password`=? WHERE `name`=?", "tom_new_password", "tom")
if err != nil {
fmt.Println("update data failed:", err.Error())
return
}
num, err := result.RowsAffected()
if err != nil {
fmt.Println("fetch row affected failed:", err.Error())
return
}
fmt.Println("update recors number", num)

删除

// 删除数据 
result, err = db.Exec("DELETE FROM `user` WHERE `name`=?", "tom")
if err != nil {
fmt.Println("delete data failed:", err.Error())
return
}
num, err = result.RowsAffected()
if err != nil {
fmt.Println("fetch row affected failed:", err.Error())
return
}
fmt.Println("delete record number", num)

事务支持 
sql.Tx用来支持事务处理

// 事务处理 
// 完全删除用户编号为2的用户数据
tx, err := db.Begin()
result, err = tx.Exec("DELETE FROM `order` WHERE uid=? ", 2)
if err != nil {
fmt.Println("delete data failed:", err.Error())
return
}
num, err = result.RowsAffected()
if err != nil {
fmt.Println("fetch row affected failed:", err.Error())
return
}
fmt.Println("delete record number", num)
result, err = tx.Exec("DELETE FROM `user` WHERE uid=? ", 2)
if err != nil {
fmt.Println("delete data failed:", err.Error())
return
}
num, err = result.RowsAffected()
if err != nil {
fmt.Println("fetch row affected failed:", err.Error())
return
}
fmt.Println("delete record number", num)
// 根据条件回滚或者提交
// tx.Rollback()
tx.Commit()

Prepared Statement 
sql.Stmt支持预备表达式,可以用来优化SQL查询提高性能,减少SQL注入的风险, DB.Prepare()和Tx.Prepare()都提供了对于预备表达式的支持。

// 预备表达式 
stmt, err := db.Prepare("DELETE FROM `order` WHERE `oid`=?")
if err != nil {
fmt.Println("fetch row affected failed:", err.Error())
return
}
result, err = stmt.Exec(1)
if err != nil {
fmt.Println("delete data failed:", err.Error())
return
}
num, err = result.RowsAffected()
if err != nil {
fmt.Println("fetch row affected failed:", err.Error())
return
}
fmt.Println("delete record number", num)

参考资料


[1]  
[2]  

转载地址:http://hqwvb.baihongyu.com/

你可能感兴趣的文章
Python PAT (Basic Level) Practice 1011 A+B 和 C
查看>>
Python PAT (Basic Level) Practice 1017 A除以B
查看>>
Python PAT (Basic Level) Practice 1042 字符统计
查看>>
spring dubbo 2.7.3 zookeeper 项目构建
查看>>
spring dubbo 报错
查看>>
如何在非 bean 对象中注入 dubbo service
查看>>
前后端分离 ajax java跨域配置 spring boot 、 spring security
查看>>
java spring boot 拦截所有请求 显示请求路径 方法 ip 等
查看>>
java spring boot jackson 配置 null字符串为"" null数组为[]
查看>>
java redistemplate 配置序列化
查看>>
ArcEngine中加载和读取Style文件或.serverstyle文件
查看>>
递归算法及经典递归例子代码实现
查看>>
Surrounded Regions
查看>>
Palindrome Partitioning
查看>>
Palindrome Partitioning II
查看>>
Clone Graph
查看>>
Gas Station
查看>>
Candy
查看>>
Single Number
查看>>
SetForeGroundWindow
查看>>