教程

上下文

qianmoQqianmoQ· 更新于 2026-09-23· 阅读 7 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

GORM 的上下文支持是一项强大的功能,它增强了 Go 应用程序中数据库操作的灵活性和控制力。它允许在不同的操作模式、超时设置以及钩子/回调和中间件集成中进行上下文管理。让我们来深入了解这些不同的方面:

单会话模式

单会话模式适用于执行单个操作。它确保特定操作在上下文的范围内执行,从而实现更好的控制和监控。

泛型 API

使用泛型 API 时,上下文作为操作方法的第一个参数直接传递:

users, err := gorm.G[User](db).Find(ctx)

传统 API

使用传统 API 时,通过 WithContext 方法传递上下文:

db.WithContext(ctx).Find(&users)

连续会话模式

连续会话模式适合执行一系列相关操作。它在这些操作之间保持上下文,这在事务等场景中尤其有用。

tx := db.WithContext(ctx)
tx.First(&user, 1)
tx.Model(&user).Update("role", "admin")

上下文超时

在上下文上设置超时可以控制长时间运行的查询的持续时间。这对于维持性能和避免数据库交互中的资源锁定至关重要。

泛型 API

使用泛型 API 时,将超时上下文直接传递给操作:

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

users, err := gorm.G[User](db).Find(ctx)

传统 API

使用传统 API 时,将超时上下文传递给 WithContext:

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

db.WithContext(ctx).Find(&users)

钩子/回调中的上下文

上下文也可以在 GORM 的钩子/回调中访问。这使得上下文信息可以在这些生命周期事件中被使用。上下文通过 Statement.Context 字段访问:

func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
  ctx := tx.Statement.Context
  
  return
}

与 Chi 中间件集成

GORM 的上下文支持扩展到了 Web 服务器中间件,例如 Chi 路由器中的中间件。这允许为 Web 请求范围内的所有数据库操作设置带有超时的上下文。

func SetDBMiddleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    timeoutContext, _ := context.WithTimeout(context.Background(), time.Second)
    ctx := context.WithValue(r.Context(), "DB", db.WithContext(timeoutContext))
    next.ServeHTTP(w, r.WithContext(ctx))
  })
}


r := chi.NewRouter()
r.Use(SetDBMiddleware)


r.Get("/", func(w http.ResponseWriter, r *http.Request) {
  db, ok := r.Context().Value("DB").(*gorm.DB)
  
})

r.Get("/user", func(w http.ResponseWriter, r *http.Request) {
  db, ok := r.Context().Value("DB").(*gorm.DB)
  
})

注意:通过 WithContext 设置 Context 是 goroutine 安全的。这确保了数据库操作在多个 goroutine 之间的安全管理。更多详情请参阅 GORM 的 Session 文档。

日志记录器集成

GORM 的日志记录器也接受 Context,可用于日志跟踪和与现有日志基础设施的集成。

更多详情请参阅 Logger 文档。

GitHub tag (latest SemVer)

评论

登录后参与评论

正在加载评论…