问答 / 122 / 4 / 创建于 8个月前 / 更新于 8个月前
感觉 Go 文档 中的例子好像不完整,函数参数中的 context 是哪来的?直接用默认的那个上下文就行?另外好像还需要处理 context 的错误?文档里好像没有。网上搜了一会儿,也看了一会儿,失去耐心了。
所谓靠谱就是最好是官方文档中的代码。我怀疑我搜索的方法不对,可能有完整的例子。如果确实没有的话,经验丰富的大佬给段代码也行。或者大型开源项目中的代码段也行,我自己试着在 github 上搜了一下,搜索代码的时候好像不能按照项目的收藏数排序。
QueryContext
database/sql 包中的 QueryContext 方法内部实现涉及多个层次的协作,以下是其核心实现机制:
database/sql
QueryContext 的基本工作流程如下:
// 伪代码表示核心逻辑 func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) { // 首先检查上下文是否已取消 if err := ctx.Err(); err != nil { return nil, err } // 获取数据库连接(会考虑上下文) dc, err := db.conn(ctx, strategy) if err != nil { return nil, err } // 执行查询(会监控上下文) return db.queryDC(ctx, dc, dc.releaseConn, nil, query, args) }
连接获取过程 (conn 方法) 会:
conn
select { case <-ctx.Done(): // 上下文取消,返回错误 return nil, ctx.Err() case conn := <-pool: // 获取到连接 return conn, nil case <-time.After(timeout): // 获取连接超时 return nil, ErrConnTimeout }
实际查询执行 (queryDC 方法) 会:
queryDC
不同数据库驱动有各自的实现方式,但通常遵循以下模式:
// 伪代码 func (mc *mysqlConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { // 启动监控 goroutine done := make(chan struct{}) defer close(done) go func() { select { case <-ctx.Done(): // 取消查询 mc.cancelQuery() case <-done: // 正常完成 } }() // 执行实际查询 return mc.query(query, args) }
net.Conn
任何时候如果上下文被取消:
这种实现确保了即使查询被取消,也不会造成资源泄漏。
直接用orm不行吗
package main import ( "context" "database/sql" "fmt" "time" _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "用户名:密码@(数据库ip)/数据库名") if err != nil { fmt.Println(err) return } ctx := context.Background() queryCtx, cancel := context.WithTimeout(ctx, 1*time.Second) // 设置超时时间为1秒 defer cancel() begin := time.Now() _, err = db.QueryContext(queryCtx, "select sleep(3)") // db sleep 3秒,模拟超时情况 end := time.Now() fmt.Println("查询耗时:", end.Sub(begin)) // 输出:查询耗时: 1.001157083s if err != nil { fmt.Println(err) // 输出超时错误:context deadline exceeded } }
我要举报该,理由是:
QueryContext内部实现解析database/sql包中的QueryContext方法内部实现涉及多个层次的协作,以下是其核心实现机制:1. 整体流程
QueryContext的基本工作流程如下:2. 关键实现细节
上下文监控
连接获取与上下文整合
连接获取过程 (
conn方法) 会:查询执行过程
实际查询执行 (
queryDC方法) 会:3. 驱动层实现
不同数据库驱动有各自的实现方式,但通常遵循以下模式:
MySQL 驱动示例
4. 超时处理机制
net.Conn的 SetDeadline 方法5. 资源清理
任何时候如果上下文被取消:
这种实现确保了即使查询被取消,也不会造成资源泄漏。
直接用orm不行吗