返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

database 1.18

发布于 2024-10-12 19:15:51 字数 2699 浏览 0 评论 0 收藏 0

sql

SQL 数据库通用接口。

db

数据库抽象,用以维持会话,执行创建、查询、事务等操作。

  • 内部连接池管理多个底层连接。按需创建、复用和释放。
  • 并发安全实现,可建立长生命周期实例。(全局变量)

使用前,须导入驱动。

package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/mattn/go-sqlite3"  // 导入驱动。
)

func main() {
    log.SetFlags(log.Lshortfile)
    
	db, err := sql.Open("sqlite3", ":memory:")
	if err != nil { log.Fatalln(err) }
    defer db.Close()

	if err := db.Ping(); err != nil {  // 测试连接。
		log.Fatalln(err)
	}

	fmt.Printf("%+v\n", db.Stats())    // 返回状态。
}

/*

{
	MaxOpenConnections:0 
	OpenConnections:1 
	InUse:0 
	Idle:1 
	WaitCount:0 
	WaitDuration:0s 
	MaxIdleClosed:0 
	MaxIdleTimeClosed:0 
	MaxLifetimeClosed:0
}

*/

源码剖析

从注册驱动开始。

// database/sql/sql.go

var (
	driversMu sync.RWMutex
	drivers   = make(map[string]driver.Driver)
)

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
}

导入驱动,它的初始化函数会调用 Register 函数进行注册。

// sqlite3.go

var driverName = "sqlite3"

func init() {
	if driverName != "" {
		sql.Register(driverName, &SQLiteDriver{})
	}
}

可用 Drivers 函数返回已注册驱动列表。

// database/sql/sql.go

func Drivers() []string {
	driversMu.RLock()
	defer driversMu.RUnlock()
    
	list := make([]string, 0, len(drivers))
	for name := range drivers {
		list = append(list, name)
	}
    
	sort.Strings(list)
	return list
}

另外, Open 不会立即创建连接。

func Open(driverName, dataSourceName string) (*DB, error) {
    
	driversMu.RLock()
	driveri, ok := drivers[driverName]
	driversMu.RUnlock()
    
	if !ok {
		return nil, fmt.Errorf("unknown driver %q", driverName)
	}

	if driverCtx, ok := driveri.(driver.DriverContext); ok {
		connector, err := driverCtx.OpenConnector(dataSourceName)
		if err != nil {
			return nil, err
		}
		return OpenDB(connector), nil
	}

	return OpenDB(dsnConnector{dsn: dataSourceName, driver: driveri}), nil
}
func OpenDB(c driver.Connector) *DB {
	ctx, cancel := context.WithCancel(context.Background())
	db := &DB{
		connector:    c,
		openerCh:     make(chan struct{}, connectionRequestQueueSize),
		lastPut:      make(map[*driverConn]string),
		connRequests: make(map[uint64]chan connRequest),
		stop:         cancel,
	}

	go db.connectionOpener(ctx)  // 详见下一节。

	return db
}

SQL database drivers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文