Files
build-web-application-with-…/5.1.md
2012-09-10 18:08:37 +08:00

4.1 KiB
Raw Blame History

#5.1 database/sql接口 Go和PHP不同的地方是他没有官方提供数据库驱动而是定义了一些标准接口用来开发数据库驱动第三方用户可以根据定义的接口来开发相应的数据库驱动其实这样做有一个好处我们按照标准接口开发的代码将来迁移数据库是相当方便的换一个数据库驱动但是底层的接口没有任何变化。那么Go都定义了那些标准接口呢让我们来详细的分析一下

##sql.Register 这个函数是database/sql里面用来注册数据库驱动的当第三方开发者开发完毕一个数据库驱动都会在驱动里面有一个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设计的巧妙之处我们知道在变量赋值的时候看到过这个是用来忽略变量的意思那么这个包引入也是这个只是引入包而不直接使用这个pkg的调用我们在2.3流程和函数里面介绍过init函数的初始化过程包在引入的时候会去初始化包内部的init函数那么我们引入上面的数据库驱动包之后会去调用init函数然后在init函数里面注册了这个数据库驱动这样我们就可以在接下来的代码中直接使用这个数据库驱动了。

##driver.Driver 数据库驱动是一个接口定义他定义了一个method Open(name string)这个方法返回一个数据库的Conn接口这个Conn只能用来进行一次goroutine的操作。

type Driver interface {
	Open(name string) (Conn, error)
}

每个驱动的这个函数都是通过name参数用来解析然后初始化一个Conn返回。

##driver.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可以进行事物操作回滚、递交等操作。

##drive.Stmt Stmt是一种准备好的状态和Conn相关联而且是只能应用于一个goroutine中不能应用在多个goroutine中。

type Stmt interface {
    Close() error
    NumInput() int
    Exec(args []Value) (Result, error)
    Query(args []Value) (Rows, error)
}

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

type Tx interface {
	Commit() error
	Rollback() error
}

##drive.Execer

##drive.Result

##drive.Rows

##drive.RowsAffected

##drive.Value

LastModified

  • Id