首页 / 更多教程 / Go源码分析系列:sql驱动加载
Go源码分析系列:sql驱动加载
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Go源码分析系列:sql驱动加载,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2900字,纯文字阅读大概需要5分钟。
内容图文
对于开发人员来说,我们不仅要知其然,更要知其所以然,不仅要知道工具如何用,更要知道,工具的原理,这也是我写这个文章系列(Go源码分析)的意义,记录的同时,也希望对大家有所帮助。
话不多说,直接开始:
-------------------------------
先说一下go语言中提供的一个sql框架(database/sql),但是呢,它只提供了一个架子,并没有具体实现,我们可以通过插件的方式注册自己想要使用的数据库,比如MySQL。
下面看一段代码:
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB // 连接池对象
func initDB() (err error) {
dsn := "user:pwd@tcp(ip:port)/db" // 用户名:密码@tcp(IP:端口)/数据库名
db, err = sql.Open("mysql", dsn) // 只会校验格式
if err != nil {
fmt.Printf("dsn:%s invalid, err = %v\n", dsn, err)
return
}
err = db.Ping() // 连接服务器校验登录信息
if err != nil {
fmt.Printf("open:%s failed, err = %v\n", dsn, err)
return
}
fmt.Printf("open:%s success\n", dsn)
return
}
代码很简单,就是建立一个mysql的数据库连接池对象,这段代码里面最重要的就是这一行代码:
import (
_ "github.com/go-sql-driver/mysql"
)
如果不加这一句,在“sql.Open("mysql", dsn)”的时候,就会告知你没有mysql的驱动,看一下“sql.Open”的源码就知道原因了:
package sql
var (
...
drivers = make(map[string]driver.Driver)
)
func Register(name string, driver driver.Driver) {
...
drivers[name] = driver
}
func Open(driverName, dataSourceName string) (*DB, error) {
...
driveri, ok := drivers[driverName]
...
return OpenDB(dsnConnector{dsn: dataSourceName, driver: driveri}), nil
}
drivers默认是空的,也就是说,只能通过Register注册驱动后,才能使用,这就是关键点了。
为什么要导“github.com/go-sql-driver/mysql”包,mysql包下的driver.go做的就是初始化注册驱动的操作:
package mysql
func init() {
sql.Register("mysql", &MySQLDriver{})
}
这也就解释了,为什么不导包,“sql.Open("mysql", dsn)”就会报错,也能充分体现出插件化的灵活性。
如果大家有兴趣,我再多说一点关于数据库连接池的知识点,看下调用的代码:
func main() {
err := initDB()
if err != nil {
fmt.Printf("init db failed, err = %v\n", err)
return
}
defer db.Close()
var u user
sql := `select id,name from user where id=?;`
row := db.QueryRow(sql, 2)
err = row.Scan(&u.id, &u.name)
if err != nil {
fmt.Printf("Scan failed, err = %v\n", err)
return
}
fmt.Printf("Scan success, u = %v\n", u)
}
关键代码在“db.QueryRow”和“row.Scan”这两行,在“db.QueryRow”之后,如果没有调用“row.Scan”,连接池就会处于一个保持连接的状态,占用资源,达到一定数量线程将会阻塞,看一下“row.Scan”中的代码实现就明白了:
func (r *Row) Scan(dest ...interface{}) error {
...
defer r.rows.Close()
...
}
Scan操作将会关闭当前QueryRow建立的连接池,所以,为了避免此情况,也有很多人会采用以下写法:
db.QueryRow(sql, 2).Scan(&u.id, &u.name)
至于连接池的大小,可以通过以下方式设置(一般放在初始化的时候):
db.SetMaxOpenConns(10)
本次分享就到这里,如果您有问题或者其他建议,欢迎留言讨论。
------------
作者寄语:
我们缺乏的常常不是编码能力,而是思考能力。
既然热爱编程,那就静下心来,要知道,每一个台阶,都可以是终点,也可以是新的起点。
内容总结
以上是互联网集市为您收集整理的Go源码分析系列:sql驱动加载全部内容,希望文章能够帮你解决Go源码分析系列:sql驱动加载所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。