go database/sql
database/sql 设计哲学非常优雅 database/sql 实现思想分析
对上层应用提供一个标准的API 对驱动层定义一个标准接口层
隔离具体的数据库 各个具体的数据库驱动实现该套接口即可被使用
应用层调用逻辑不依赖具体的数据库 其使用的是sql提供的标准API
三大功能
在内部实现一个连接池 内部通过锁实现并发访问的安全性 内部实现数据类型的自动转换

驱动层实现的接口和应用层的调用接口几乎一模一样
使应用程序调用者和驱动的实现者看到的接口视角的一致性
则也算一种编程哲学 增强功能但是调用接口不变 一般的理解是增强功能要增加接口 但是sql包的实现几乎没有增加太多的调用接口而实现功能增强

把复杂功能放在sql包内部实现 并发的安全性支持 连接池的管理
为访问DB提供一个抽象体 看不到连接 连接完全在内部实现中隐藏了
编程哲学 面向接口编程
sql包的实现者教科书般的告诉实现抽象型 平台型中间件的方法
抽象底层实现者接口 中间件面向接口层实现平台级层逻辑
对外提供一套统一的调用API 隔离底层实现者和上层调用者
基于该种思想可以抽象的平台型中间件有
日志记录 记录到文件 记录到DB 写到网络
session管理
存放在内存  存放在DB  存放在文件
程序配置  各种配置文件 DB 其他中间件
面向组合的编程
sql包中定义数据结构组合了driver层的接口变量和内部数据元素 可看作golang独有的组合编程模式
分层实现
层内高内聚 层间低耦合 隐藏实现的复杂性 通过接口粘合
驱动接口设计特点
驱动层设计很简单 没有并发锁的控制
驱动层的设计是基于单个连接的 没有考虑连接池
驱动层事务 Tx 和 Stmt 是独立分离的 Tx 只有两个简单的方法就是 Commit() 和 Rollback()
驱动的具体实现者只需要在单个连接上实现驱动层的API接口即可
driver包的数据结构
src\database\sql\driver  > package driver  > 定义数据库的访问接口 driver.go / types.go >
type value interface{}
interface > Driver.methods.Open(name string)(Conn,error)
  > Conn.methods.Prepare(query string)(Stmt,error)
         Conn.methods.Close() error
        Conn.methods.Begin() (Tx,error)
 >Stmt.methods.NumInput() interface
         Stmt.methods.Exec(args []Value)(Result,error)              
         Stmt.methods.Query(args []Value)(Rows,error)
         Stmt.methods.Close() error
  >Tx.methods.Commit() error
          Tx.methods.Rollback() error
 >Result.methods.LastInsertId()(int64,error)
               Result.methods.RowsAffected()(int64,error)
 >Rows.methods.Columns()[]string
               Rows.methods.Close() error
               Rows.methods.Next(dest []Value) error
  >Queryer.methods.Query(query string,args []Value)(Rows,error)
  >ValueConverter.methods.ConverValue(v interface{})(Value,error)
  >Value.methods.Value()(Value,error)
调用关系
driver接口引用逻辑.driver.Driver.Open(name string)(Conn,error).driver.Conn >
Close() error
Begin()(Tx,error).driver.Tx
Prepare(query string)(Stmt,error) > driver.Stmt >
>Exec(args []Value)(Result,error) > driver.Result >| LastInsertId()(int64,error) | RowsAffected()(int64,error)
>Query(args []Value)(Rows,error)>driver.Rows > |Columns()[]string  |Close() error  |Next(dest []Value) error

驱动注册
具体的数据库驱动只需要按照接口层的定义 实现api 然后在sql包的全局驱动切片sql.drivers中注册即可。
var (
driversMu sync.RWMutex
drivers   = make(map[string]driver.Driver)                                                       
)  
func Register(name string, driver driver.Driver) {
mysql 驱动 github.com/go-sql-driver/mysql注册过程
src/github.com/go-sql-driver/mysql/driver.go
func init() {                                                                                         
     sql.Register("mysql", &MySQLDriver{})                                                             
}
package sql 最核心的的数据结构是 sql.DB
其为上层应用程序提供一个统一的抽象体 它不代表一个 数据库连接 也不代表一个 连接池
sql 包 为了实现 并发访问 安全控制 连接池 等诸多功能而设计的一个 综合 抽象数据结构
type DB struct {#通过 driverName 获取 driver 通过 driver 的 Open() 方法获得到 DB的原始连接 sql.Open() 创建一个 DB 实例
   driver driver.Driver #DB连接字符串 创建 DB实例 不会理解创建连接 只有使用的时候才去创建连接
   dsn    string
  // numClosed is an atomic counter which represents a total number of
  // closed connections. Stmt.openStmt checks it before cleaning closed                            
  // connections in Stmt.css.
#启动以来关闭的连接数
 numClosed    uint64   
 mu           sync.Mutex // protects following fields
 freeConn     []*driverConn  #空闲连接池 使用后的连接立马放到连接池中    
#当db.numOpen >= db.maxOpen时 排队等待创建的连接都会添加到改数据结构中
 connRequests []chan connRequest
 numOpen      int #当前打开的连接数
#当前等待创建的连接数 len(connRequests)和 pendingOpens 区别是 一个是等待排队连接 还没有获得创建连接的资格 一个是已经拿到资格准备创建
 pendingOpens int
 // Used to signal the need for new connections
 // a goroutine running connectionOpener() reads on this chan and
 // maybeOpenNewConnections sends on the chan (one send per needed connection)
 // It is closed during db.Close(). The close tells the connectionOpener
 // goroutine to exit.
#等待database 启动一个独立的goroutine创建连接所需连接 将创建的连接直接发到connRequests chan中或者放到空闲连接池
 openerCh chan struct{}
#关闭状态
 closed   bool
#依赖关系维护 用户维护DB和其他数据结构的依赖关系 由于数据结构之间存在相互引用和依赖以及复用 在清理关闭资源时必须把依赖关系给释放掉
 dep      map[finalCloser]depSet
 lastPut  map[*driverConn]string // stacktrace of last conn's put; debug only
#最大的空闲连接数
 maxIdle  int                    // zero means defaultMaxIdleConns; negative means 0
#最大连接数 0表示不受限制
  maxOpen  int                    // <= 0 means unlimited
 }


 


database sql和database相关