现在,你已经导入了驱动package,那么你就可以创建一个数据库对象了,即sql.DB.

为了创建sql.DB,你可使用sql.Open(),它返回一个*sql.DB.

func main() {
	db, err := sql.Open("mysql",
		"user:password@tcp(127.0.0.1:3306)/hello")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
}

下面是示例的一些说明:

  1. sql.Open的第一个参数是驱动的名称.这是驱动注册自己到database/sql时所使用的字符串.为了避免混淆,通常是与驱动的包名相同.例如,mysql用于github.com/go-sql-driver/mysql.但也有一些驱动名称不遵循约定(使用数据库名称),比如,sqlite3用于github.com/mattn/go-sqlite3, postgres用于github.com/lib/pq.
  2. 第二个参数是驱动的特定语法,用来告诉驱动如何去访问数据库.在这个例子中,我们是连接到了本地MySQL实例中的"hello"数据库.
  3. 通常你应该(绝大多数情况下)检查和处理database/sql所有操作返回的error.我们将在以后讨论在特定条件下也可不处理的情况.
  4. 通常情况下,sql.DB的生命周期不会超出function的范围,此时应该添加defer db.Close()

与直觉不同,sql.Open()并不会建立任何与数据库的连接,也不验证驱动的连接参数.它只是简单地准备好数据库抽象以备后用.第一个实际意义上的与数据库的连接会被延迟到第一次使用时才建立.如果你想立刻检查数据库是否可用(比如,检查你是否可以建立网络连接并登入数据库),可使用db.Ping(),且记得检查error.

err = db.Ping()
if err != nil {
	// do something here
}

虽然习惯上,当使用完数据库时需Close()掉数据库,然而,sql.DB对象是被设计成支持长连接的.请不要频繁地Open()Close()数据库.相反,为每一个需要访问的数据库创建一个其独有的sql.DB对象,在程序访问完数据库前一直持有它.在需要时传递它,或让它全局可用,但是要确保是打开的.还有,不要在短暂的function中使用Open()Close(),而是通过将sql.DB作为参数传入短暂function的方式代替.

如果不将sql.DB视为长期对象,你将会碰到诸如此类的问题,比如无法复用和共享连接,网络资源失控,因为许多tcp连接停留在TIME_WAIT状态而导致间断性失败.此类问题意味着你没用按照database/sql的设计意图来使用它.

现在是时候使用sql.DB对象了.