go语言访问数据库

简介: go语言访问数据库

Go 与 PHP 不同的地方是 Go 没有官方提供数据库驱动,而是为开发者开发数据库驱动定
义了一些标准接口,开发者可以根据定义的接口来开发相应的数据库驱动,这样做有一个
好处,只要按照标准接口开发的代码, 以后需要迁移数据库时,不需要任何修改。那么 Go
都定义了哪些标准接口呢?让我们来详细的分析一下
sql.Register
这个存在于 database/sql 的函数是用来注册数据库驱动的,当第三方开发者开发数据库驱
动时,都会实现 init 函数,在 init 里面会调用这个 Register(name string, driver
driver.Driver)完成本驱动的注册。
我们来看一下 mymysql、sqlite3 的驱动里面都是怎么调用的:
//https://github.com/mattn/go-sqlite3 驱动
func init() {
sql.Register("sqlite3", &SQLiteDriver{})
}
//https://github.com/mikespook/mymysql 驱动
// Driver automatically registered in database/sql
var d = Driver{proto: "tcp", raddr: "127.0.0.1:3306"}
func init() {
Register("SET NAMES utf8")
sql.Register("mymysql", &d)
}
我们看到第三方数据库驱动都是通过调用这个函数来注册自己的数据库驱动名称以及相应
的 driver 实现。在 database/sql 内部通过一个 map 来存储用户定义的相应驱动。
var drivers = make(map[string]driver.Driver)
drivers[name] = driver
因此通过 database/sql 的注册函数可以同时注册多个数据库驱动,只要不重复。
在我们使用 database/sql 接口和第三方库的时候经常看到如下:
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
新手都会被这个_所迷惑,其实这个就是 Go 设计的巧妙之处,我们在变量赋值的时候经常
看到这个符号,它是用来忽略变量赋值的占位符,那么包引入用到这个符号也是相似的作
用,这儿使用_的意思是引入后面的包名而不直接使用这个包中定义的函数,变量等资源。
我们在 2.3 节流程和函数的一节中介绍过 init 函数的初始化过程,包在引入的时候会自动调
用包的 init 函数以完成对包的初始化。因此,我们引入上面的数据库驱动包之后要手动去调
用 init 函数,然后在 init 函数里面注册这个数据库驱动,这样我们就可以在接下来的代码中
直接使用这个数据库驱动了。
driver.Driver
Driver 是一个数据库驱动的接口,他定义了一个 method: Open(name string),这个方法
返回一个数据库的 Conn 接口。
type Driver interface {
Open(name string) (Conn, error)
}
返回的 Conn 只能用来进行一次 goroutine 的操作,也就是说不能把这个 Conn 应用于 Go
的多个 goroutine 里面。如下代码会出现错误
...
go goroutineA (Conn) //执行查询操作
go goroutineB (Conn) //执行插入操作
...
上面这样的代码可能会使 Go 不知道某个操作究竟是由哪个 goroutine 发起的,从而导致数
据混乱,比如可能会把 goroutineA 里面执行的查询操作的结果返回给 goroutineB 从而使 B
错误地把此结果当成自己执行的插入数据。
第三方驱动都会定义这个函数,它会解析 name 参数来获取相关数据库的连接信息,解析
完成后,它将使用此信息来初始化一个 Conn 并返回它。
driver.Conn
Conn 是一个数据库连接的接口定义,他定义了一系列方法,这个 Conn 只能应用在一个
goroutine 里面,不能使用在多个 goroutine 里面,详情请参考上面的说明。
type Conn interface {
Prepare(query string) (Stmt, error)
Close() error
Begin() (Tx, error)
}
Prepare 函数返回与当前连接相关的执行 Sql 语句的准备状态,可以进行查询、删除等操作。
Close 函数关闭当前的连接,执行释放连接拥有的资源等清理工作。因为驱动实现了
database/sql 里面建议的 conn pool,所以你不用再去实现缓存 conn 之类的,这样会容易
引起问题。
Begin 函数返回一个代表事务处理的 Tx,通过它你可以进行查询,更新等操作,或者对事务
进行回滚、递交。
driver.Stmt
Stmt 是一种准备好的状态,和 Conn 相关联,而且只能应用于一个 goroutine 中,不能应
用于多个 goroutine。
type Stmt interface {
Close() error
NumInput() int
Exec(args []Value) (Result, error)
Query(args []Value) (Rows, error)
}
Close 函数关闭当前的链接状态,但是如果当前正在执行 query,query 还是有效返回 rows
数据。
NumInput 函数返回当前预留参数的个数,当返回>=0 时数据库驱动就会智能检查调用者的
参数。当数据库驱动包不知道预留参数的时候,返回-1。
Exec 函数执行 Prepare 准备好的 sql,传入参数执行 update/insert 等操作,返回 Result 数

Query 函数执行 Prepare 准备好的 sql,传入需要的参数执行 select 操作,返回 Rows 结果

driver.Tx
事务处理一般就两个过程,递交或者回滚。数据库驱动里面也只需要实现这两个函数就可以
type Tx interface {
Commit() error
Rollback() error
}
这两个函数一个用来递交一个事务,一个用来回滚事务。
driver.Execer
这是一个 Conn 可选择实现的接口
type Execer interface {
Exec(query string, args []Value) (Result, error)
}
如果这个接口没有定义,那么在调用 DB.Exec,就会首先调用 Prepare 返回 Stmt,然后执行
Stmt 的 Exec,然后关闭 Stmt。
driver.Result
这个是执行 Update/Insert 等操作返回的结果接口定义
type Result interface {
LastInsertId() (int64, error)
RowsAffected() (int64, error)
}
LastInsertId 函数返回由数据库执行插入操作得到的自增 ID 号。
RowsAffected 函数返回 query 操作影响的数据条目数。
driver.Rows
Rows 是执行查询返回的结果集接口定义
type Rows interface {
Columns() []string
Close() error
Next(dest []Value) error
}
Columns 函数返回查询数据库表的字段信息,这个返回的 slice 和 sql 查询的字段一一对应,
而不是返回整个表的所有字段。
Close 函数用来关闭 Rows 迭代器。
Next 函数用来返回下一条数据,把数据赋值给 dest。dest 里面的元素必须是 driver.Value 的
值除了 string,返回的数据里面所有的 string 都必须要转换成[]byte。如果最后没数据了,
Next 函数最后返回 io.EOF。
driver.RowsAffected
RowsAffested 其实就是一个 int64 的别名,但是他实现了 Result 接口,用来底层实现
Result 的表示方式
type RowsAffected int64
func (RowsAffected) LastInsertId() (int64, error)
func (v RowsAffected) RowsAffected() (int64, error)
driver.Value
Value 其实就是一个空接口,他可以容纳任何的数据
type Value interface{}
drive 的 Value 是驱动必须能够操作的 Value,Value 要么是 nil,要么是下面的任意一种
int64
float64
bool
[]byte
string [*]除了 Rows.Next 返回的不能是 string.
time.Time
driver.ValueConverter
ValueConverter 接口定义了如何把一个普通的值转化成 driver.Value 的接口
type ValueConverter interface {
ConvertValue(v interface{}) (Value, error)
}
在开发的数据库驱动包里面实现这个接口的函数在很多地方会使用到,这个
ValueConverter 有很多好处:
• 转化 driver.value 到数据库表相应的字段,例如 int64 的数据如何转化成数据库表
uint16 字段
• 把数据库查询结果转化成 driver.Value 值
• 在 scan 函数里面如何把 dirve.Value 值转化成用户定义的值
driver.Valuer
Valuer 接口定义了返回一个 driver.Value 的方式
type Valuer interface {
Value() (Value, error)
}
很多类型都实现了这个 Value 方法,用来自身与 driver.Value 的转化。
通过上面的讲解,你应该对于驱动的开发有了一个基本的了解,一个驱动只要实现了这些
接口就能完成增删查改等基本操作了,剩下的就是与相应的数据库进行数据交互等细节问
题了。

目录
相关文章
|
9天前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
45 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
28天前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
29天前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
100 71
|
28天前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
105 67
|
3天前
|
算法 安全 Go
Go 语言中实现 RSA 加解密、签名验证算法
随着互联网的发展,安全需求日益增长。非对称加密算法RSA成为密码学中的重要代表。本文介绍如何使用Go语言和[forgoer/openssl](https://github.com/forgoer/openssl)库简化RSA加解密操作,包括秘钥生成、加解密及签名验证。该库还支持AES、DES等常用算法,安装简便,代码示例清晰易懂。
29 16
|
6天前
|
监控 算法 安全
解锁企业计算机监控的关键:基于 Go 语言的精准洞察算法
企业计算机监控在数字化浪潮下至关重要,旨在保障信息资产安全与高效运营。利用Go语言的并发编程和系统交互能力,通过进程监控、网络行为分析及应用程序使用记录等手段,实时掌握计算机运行状态。具体实现包括获取进程信息、解析网络数据包、记录应用使用时长等,确保企业信息安全合规,提升工作效率。本文转载自:[VIPShare](https://www.vipshare.com)。
19 0
|
20天前
|
Go 数据安全/隐私保护 UED
优化Go语言中的网络连接:设置代理超时参数
优化Go语言中的网络连接:设置代理超时参数
|
11天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
38 3
|
11天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
38 3
|
11天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
52 2