Go语言 Web开发(5)数据库标准接口解析

Go没有官方提供的数据库驱动,而是定义了一些数据库驱动标准接口,这样我们可以根据定义的接口来开发相应的数据库驱动,后期进行数据库转移时就不需要进行修改。

我们来看看Go有哪些数据库标准接口
①sql.Register
在开发数据库驱动时,都会实现init函数,然后在init函数中调用sql的Register函数完成驱动的注册。
sql的Register函数源码

func Register(name string, driver driver.Driver) {
   driversMu.Lock()
   defer driversMu.Unlock()
   if driver == nil {
      panic("sql: Register driver is nil")
   }
   if _, dup := drivers[name]; dup { //不能注册重复的数据库驱动
      panic("sql: Register called twice for driver " + name)
   }
   drivers[name] = driver
}

使用init函数调用sql的Register函数完成驱动的注册示例

示例一

func init() {
sql.Register("sqlite3", &SQLiteDriver{})
}

实列二

var d = Driver{proto: "tcp", raddr: "127.0.0.1:3306"}
func init() {
Register("SET NAMES utf8")
sql.Register("mymysql", &d)
}

所有注册过的数据库驱动都会存储在一个map中

drivers   = make(map[string]driver.Driver)

②driver.Driver
这也是一个数据库驱动标准接口,关于它的源码说明如下:

type Driver interface {
   // Open返回与数据库的新连接。
   //名称是特定于驱动程序的格式的字符串。
   // Open可以返回一个缓存连接(一个先前已关闭),但这样做是不必要的; sql包维护一个空闲连接池,以便有效地重用。
   //返回的连接一次只能由一个goroutine使用。
   Open(name string) (Conn, error)
}

第三方驱动都会定义这个函数,它会解析name参数来获取相关数据库的连接信息,解析完成后,它将使用此信息来初始化一个Conn并返回它。

③driver.Conn
这是一个数据库连接的接口,只能应用在一个goroutine里面,不能使用在多个goroutine里面,它定义的一些方法如下所示:

// Conn是与数据库的连接。 它不是由多个goroutines同时使用的。
// Conn被认为是有状态的。
type Conn interface {
    // 返回与当前连接相关的执行Sql语句的准备状态,可以进行查询、删除等操作。
   Prepare(query string) (Stmt, error)

    //关闭当前的连接并可能停止任何当前准备好的语句和事务,将此连接标记为不再使用。
    //因为sql包维护一个空闲的连接池,并且只有在空闲连接过剩时才调用Close,所以驱动程序不需要进行自己的连接缓存。
   Close() error

    //返回一个代表事务处理的Tx,通过它你可以进行查询,更新等操作,或者对事务进行回滚、递交。
    //不推荐使用:驱动程序应该实现ConnBeginTx(或者另外)。
   Begin() (Tx, error)
}

④driver.Stmt
关于它的源码解释如下所示:

// Stmt是一个准备好的声明。 这是一个康恩而不是
//同时使用多个goroutines。
type Stmt interface {
    //关闭语句。
    //从Go 1.1开始,如果Stmt正在被任何查询使用,它将不会被关闭。
   Close() error

    // NumInput返回占位符参数的数量。
    //如果NumInput返回> = 0,则在调用语句的Exec或Query方法之前,sql包将从调用者检查参数计数并将错误返回给调用者。
    //如果驱动程序不知道占位符数,NumInput也可能返回-1。 在这种情况下,sql包将无法检查Exec或Query参数计数。
   NumInput() int

    // Exec执行不返回行的查询,例如INSERT或UPDATE。
    //不推荐使用:驱动程序应该实现StmtExecContext(或另外)。
   Exec(args []Value) (Result, error)

    // Query执行可能返回行的查询,例如SELECT。
    //不推荐使用:驱动程序应该实现StmtQueryContext(或另外)。
   Query(args []Value) (Rows, error)
}

⑤driver.Tx
事务处理一般就两个过程,递交或者回滚。数据库驱动里面也只需要实现这两个函数就可以

type Tx interface {
   Commit() error //递交一个事务
   Rollback() error //用来回滚事务
}

⑥driver.Execer
作为Conn可选择实现的一个接口,关于它的源码解释如下所示

// Execer是一个可选的接口,可以由Conn实现。
//如果Conn既不实现ExecerContext也不实现Execer Execer,则sql包的DB.Exec将首先准备一个查询,执行该语句,然后关闭该语句。
// Exec可能会返回ErrSkip。
//不推荐使用:驱动程序应该实现ExecerContext。
type Execer interface {
   Exec(query string, args []Value) (Result, error)
}

⑦driver.Result
这个是执行Update/Insert等操作返回的结果接口定义,关于它的源码解释如下:

//Result是查询执行的结果接口。
type Result interface {
   // LastInsertId返回数据库的自动生成的ID,例如,INSERT到具有主键的表中。
   LastInsertId() (int64, error)

   // RowsAffected返回受查询影响的行数。
   RowsAffected() (int64, error)
}

⑧driver.Rows
Rows是执行查询返回的结果集接口定义,关于它的源码解释如下:

// Rows是执行查询结果的迭代器。
type Rows interface {
   //返回列的名称。 从切片的长度推断结果的列数。 如果未知特定列名称,则应为该条目返回空字符串。
   Columns() []string

    // Close关闭行迭代器。
   Close() error
    
  //调用Next以将下一行数据填充到提供的切片中。 提供的切片与Columns()的宽度相同。
  //当没有更多行时,Next应该返回io.EOF。
  //不应将dest写入Next之外。 关闭行时应小心,不要修改dest中保存的缓冲区。
   Next(dest []Value) error
}

⑨driver.Value
Value其实就是一个空接口,他可以容纳任何的数据

//值是驱动程序必须能够处理的值。
//它可以是nil,由数据库驱动程序的Name Value Checker接口处理的类型,或者是以下类型之一的实例:
//int64,float64,bool,[]byte,string,time.Time
type Value interface{}

⑩driver.RowsAffected
RowsAffested其实就是一个int64的别名,但是他实现了Result接口,用来底层实现Result的表示方式

// RowsAffected实现INSERT或UPDATE操作的结果,该操作会改变多个行。
type RowsAffected int64

var _ Result = RowsAffected(0)

func (RowsAffected) LastInsertId() (int64, error) {
   return 0, errors.New("no LastInsertId available")
}

func (v RowsAffected) RowsAffected() (int64, error) {
   return int64(v), nil
}

11 driver.ValueConverter
ValueConverter接口定义了如何把一个普通的值转化成driver.Value的接口

// ValueConverter是提供ConvertValue方法的接口。
//驱动程序包提供了ValueConverter的各种实现,以提供驱动程序之间转换的一致实现。 ValueConverters有几个用途:
// *从sql包提供的Value类型转换为数据库表的特定列类型并确保它适合,例如确保特定的int64适合表的uint16列。
// *将数据库中给定的值转换为其中一个驱动值类型。
// *由sql包,用于从驱动程序的Value类型转换为扫描中的用户类型。
type ValueConverter interface {
   // ConvertValue将值转换为驱动程序值。
   ConvertValue(v interface{}) (Value, error)
}

12 driver.Valuer
Valuer接口定义了返回一个driver.Value的方式

// Valuer是提供Value方法的接口。
//实现Valuer接口的类型能够将自身转换为驱动程序值。
type Valuer interface {
    // Value返回驱动程序值。
   Value() (Value, error)
}

参考书籍:《Go Web编程》

    原文作者:小杰的快乐时光
    原文地址: https://www.jianshu.com/p/a8f4090c357b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞