程序在对数据库执行任何操作之前,都需要先与数据库进行连接,代码清单6-7展示了实现这一动作的具体过程:程序首先使用Db变量定义了一个指向sql.DB结构的指针,然后使用init()函数来初始化这个变量(Go语言的每个包都会自动调用定义在包内的init()函数)。

代码清单6-7 用于创建数据库句柄的函数

func init() {    
    var err error    
    Db, err = sql.Open("postgres", "user=gwp dbname=gwp password=gwp sslmode=disable") //①
    if err != nil {        
        panic(err)    
    }
}

sql.DB结构是一个数据库句柄(handle),它代表的是一个包含了零个或任意多个数据库连接的连接池(pool),这个连接池由sql包管理。程序可以通过调用Open函数,并将相应的数据库驱动名字(driver name)以及数据源名字(data source name)传递给该函数来建立与数据库的连接。比如,在上面展示的例子中,程序使用的是postgres驱动。数据源名字是一个特定于数据库驱动的字符串,它会告诉驱动应该如何与数据库进行连接。Open函数在执行之后会返回一个指向sql.DB结构的指针作为结果。

需要注意的是,Open函数在执行时并不会真正地与数据库进行连接,它甚至不会检查用户给定的参数:Open函数的真正作用是设置好连接数据库所需的各个结构,并以惰性的方式,等到真正需要时才建立相应的数据库连接。

此外,因为sql.DB只是一个句柄而不是实际的连接,而这个句柄代表的是一个会自动对连接进行管理的连接池,所以尽管用户可以手动关闭sql.DB,但是在实际中通常并不需要这样做。在上面展示的例子中,程序通过全局定义的Db变量在各个CRUD方法以及函数中使用sql.DB结构;但除此之外,我们也可以选择在创建sql.DB结构之后,通过向方法或者函数传递这个结构的方式来使用它。

到目前为止,我们讨论的都是Open函数,这个函数接受数据库驱动名字和数据源名字作为参数,然后返回一个sql.DB结构作为结果。那么程序本身又是如何获取数据库驱动的呢?一般来说,程序都会向Register函数提供一个数据库驱动名字以及一个实现了driver.Driver接口的结构,以此来注册将要用到的数据库驱动,就像这样:

sql.Register("postgres", &drv{})

这个例子中的postgres就是数据库驱动的名字,而drv则是实现了Driver接口的结构。你也许已经注意到了,前面展示的数据库程序并没有包含类似的注册代码,这是因为程序使用的第三方Postgres驱动在被导入的时候已经自行实现了注册:

import (    
    "fmt"    
    "database/sql"    
    _ "github.com/lib/pq"
)

上面这段代码中的github.com/lib/pq包就是程序导入的Postgres驱动,在导入这个包之后,包内定义的init函数就会被调用,并对其自身进行注册。因为Go语言没有提供任何官方数据库驱动,所以Go语言的所有数据库驱动都是第三方函数库,并且这些库必须遵守sql.driver包中定义的接口。注意,因为程序在操作数据库的时候只需要用到database/sql,而不需要直接使用数据库驱动,所以程序在导入Postgres数据库驱动的时候将这个包的名字设置成了下划线_。这种引用数据库驱动的方式可以让用户在不修改代码的情况下升级驱动,或者修改驱动实现。

至于安装驱动这一操作,则可以通过在命令行里执行以下命令来完成:

go get "github.com/lib/pq"

这一命令会从代码库中获取驱动的具体代码,并将这些代码放置到包库(package repository)里面,当需要用到这个驱动时,编译器就会把驱动代码与用户编写的代码一同编译。

results matching ""

    No results matching ""