返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

context

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

添加上下文,避免操作阻塞。

package main

import (
	"context"
	"database/sql"
	"time"
	"log"

	_ "github.com/mattn/go-sqlite3"
)


var (
	db *sql.DB
	
	ctx = context.Background()
	timeout = time.Millisecond
)

func ping() {
	ctx, cancel := context.WithTimeout(ctx, timeout)
	defer cancel()

	var name string
	err := db.QueryRowContext(ctx, `SELECT name FROM user`).Scan(&name)

	if err == context.DeadlineExceeded {
		println("timeout!")
	} else if err != nil { 
		log.Println(err) 
	} else {
		println(name)
	}

	// select {
	// case <- ctx.Done(): println("timeout")
	// default:
	// }	
}

func main() {
	db, _ = sql.Open("sqlite3", "./test.db")
	ping()
}

源码剖析

所有操作都有其上下文版本。

// database/sql/sql.go

func (db *DB) Query(query string, args ...any) (*Rows, error) {
	return db.QueryContext(context.Background(), query, args...)
}

func (db *DB) QueryContext(ctx context.Context, ...) (*Rows, error) {
	return db.query(ctx, query, args, alwaysNewConn)
}
func (db *DB) query(ctx context.Context, ...) (*Rows, error) {
	dc, err := db.conn(ctx, strategy)
	return db.queryDC(ctx, nil, dc, dc.releaseConn, query, args)
}

func (db *DB) queryDC(ctx, txctx context.Context, ...) (*Rows, error) {
	rowsi, err = ctxDriverQuery(ctx, queryerCtx, queryer, query, nvdargs)
}

类似 ctxDriverQuery 这样的包装函数,专门针对上下文做出反应。

// database/sql/ctxutil.go

func ctxDriverQuery(ctx context.Context, ...) (driver.Rows, error) {
	select {
	default:
	case <-ctx.Done():
		return nil, ctx.Err()
	}
    
	return queryer.Query(query, dargs)
}

在操作内部,也会建立上下文应对机制。

// database/sql/sql.go

func (db *DB) queryDC(ctx, txctx context.Context, ...) (*Rows, error) {
	rows.initContextClose(ctx, txctx)
}
func (rs *Rows) initContextClose(ctx, txctx context.Context) {
	ctx, rs.cancel = context.WithCancel(ctx)
	go rs.awaitDone(ctx, txctx)
}

func (rs *Rows) awaitDone(ctx, txctx context.Context) {
	select {
	case <-ctx.Done():
	case <-txctxDone:
	}
	rs.close(ctx.Err())
}

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

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

发布评论

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