这是我参与「第五届青训营」伴学笔记创作活动的第 9 天
前言
GORM的实现主要是对 database/sql的进一步封装,本文主要对database/sql的设计原理进行介绍。
接口
database/sql是go语言的标准库,为访问关系型数据库提供通用的接口,不同的数据库实现标准库中的接口,应用程序即可通过标准库中的方法读写数据库中的数据。
关系型数据库主要需要实现的是Driver接口,即database/sql/driver.Driver,接口中只包含一个 Open 方法。
Open 方法接受一个数据库连接串作为输入参数并返回一个特定数据库的连接,作为参数的数据库连接串是数据库特定的格式,这个返回的连接仍然是一个接口。
标准库中全部接口的树形结构如下:
实现原理(以MySQL为例)
-
注册:
database/sql中提供了database/sql.Register来注册驱动,其package内部包含中管理所有数据库驱动的哈希。MySQL在go-sql-driver/mysql/mysql.init中会调用Register方法来将实现了database/sql/driver.Driver接口的结构体注册到全局的驱动列表中。 -
连接:实现驱动注册后,可以进行数据库连接,即使用
database/sql.Open传入驱动名和dsn获取特定数据库连接,并返回一个database/sql.DB结构体。结构体
database/sql.DB在刚刚初始化时不会包含任何的数据库连接,它持有的数据库连接池会在真正应用程序申请连接时在单独的 Goroutine 中获取。database/sql.DB.connectionOpener方法中包含一个不会退出的循环,每当该 Goroutine 收到了请求时都会调用database/sql.DB.openNewConnection。 -
查询:查询数据库调用的是
database/sql.DB.Querry方法,入参是SQL语句和SQL语句中的参数,主要分为获取连接和执行查询两部分。在执行查询过程中,调用database/sql.ctxDriverQuery会判断当前的查询上下文究竟实现了哪个接口,然后调用对应接口的Query或者QueryContext。
总结
database/sql标准库作为中间层通过层层抽象为不同的关系型数据库提供了统一的接口,使得应用程序可以直接调用而不关注实现细节,是非常值得学习的编程思想。