00:00:00
50.ent 客户端封装
1 ent_client.go 代码详细解释
ent_client.go 是一个位于 entgo 包中的工具类文件,主要提供了对 Ent 框架数据库客户端的封装以及创建数据库驱动的功能。下面是对该文件的详细分析:
1.1 导入的包
go
import (
"context"
"database/sql"
"errors"
"fmt"
"time"
"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
"github.com/XSAM/otelsql"
entSql "entgo.io/ent/dialect/sql"
)导入了必要的标准库包和第三方包,包括:
- 标准库:
context(上下文)、database/sql(数据库接口)、errors(错误处理)、fmt(格式化)、time(时间处理) - OpenTelemetry 相关:用于分布式追踪和指标收集
- Ent 框架的 SQL 方言包
1.2 接口定义
go
type EntClientInterface interface {
Close() error
}定义了一个简单的接口 EntClientInterface,只包含一个 Close() 方法,用于关闭数据库连接。
1.3 泛型结构体定义
go
type EntClient[T EntClientInterface] struct {
db T
drv *entSql.Driver
}使用 Go 泛型定义了 EntClient 结构体,其中:
db字段:泛型类型T,必须实现EntClientInterface接口drv字段:指向entSql.Driver类型的指针,表示 Ent 框架的 SQL 驱动
1.4 构造函数
go
func NewEntClient[T EntClientInterface](db T, drv *entSql.Driver) *EntClient[T] {
return &EntClient[T]{
db: db,
drv: drv,
}
}创建并返回一个新的 EntClient 实例,接收两个参数:
db:实现了EntClientInterface接口的数据库客户端drv:Ent 框架的 SQL 驱动
1.5 访问器方法
go
func (c *EntClient[T]) Client() T {
return c.db
}
func (c *EntClient[T]) Driver() *entSql.Driver {
return c.drv
}
func (c *EntClient[T]) DB() *sql.DB {
return c.drv.DB()
}提供了三个访问器方法:
Client():返回底层数据库客户端Driver():返回 Ent SQL 驱动DB():返回标准库的*sql.DB对象
1.6 数据库操作方法
go
// Close 关闭数据库连接
func (c *EntClient[T]) Close() error {
return c.db.Close()
}
// Query 查询数据
func (c *EntClient[T]) Query(ctx context.Context, query string, args, v any) error {
return c.Driver().Query(ctx, query, args, v)
}
func (c *EntClient[T]) Exec(ctx context.Context, query string, args, v any) error {
return c.Driver().Exec(ctx, query, args, v)
}提供了三个数据库操作方法:
Close():关闭数据库连接,调用底层客户端的Close()方法Query():执行 SQL 查询,通过 Ent 驱动执行Exec():执行 SQL 语句(如插入、更新、删除),通过 Ent 驱动执行
1.7 连接池配置方法
go
// SetConnectionOption 设置连接配置
func (c *EntClient[T]) SetConnectionOption(maxIdleConnections, maxOpenConnections int, connMaxLifetime time.Duration) {
// 连接池中最多保留的空闲连接数量
c.DB().SetMaxIdleConns(maxIdleConnections)
// 连接池在同一时间打开连接的最大数量
c.DB().SetMaxOpenConns(maxOpenConnections)
// 连接可重用的最大时间长度
c.DB().SetConnMaxLifetime(connMaxLifetime)
}用于设置数据库连接池的参数:
maxIdleConnections:连接池中最多保留的空闲连接数量maxOpenConnections:连接池在同一时间打开连接的最大数量connMaxLifetime:连接可重用的最大时间长度
1.8 辅助函数
go
func driverNameToSemConvKeyValue(driverName string) attribute.KeyValue {
switch driverName {
case "mariadb":
return semconv.DBSystemMariaDB
case "mysql":
return semconv.DBSystemMySQL
case "postgresql":
return semconv.DBSystemPostgreSQL
case "sqlite":
return semconv.DBSystemSqlite
default:
return semconv.DBSystemKey.String(driverName)
}
}根据数据库驱动名称返回对应的 OpenTelemetry 语义化属性值,支持常见的数据库类型。
1.9 驱动创建函数
go
// CreateDriver 创建数据库驱动
func CreateDriver(driverName, dsn string, enableTrace, enableMetrics bool) (*entSql.Driver, error) {
var db *sql.DB
var drv *entSql.Driver
var err error
if enableTrace {
// Connect to database
if db, err = otelsql.Open(driverName, dsn, otelsql.WithAttributes(
driverNameToSemConvKeyValue(driverName),
)); err != nil {
return nil, errors.New(fmt.Sprintf("failed opening connection to db: %v", err))
}
drv = entSql.OpenDB(driverName, db)
} else {
if drv, err = entSql.Open(driverName, dsn); err != nil {
return nil, errors.New(fmt.Sprintf("failed opening connection to db: %v", err))
}
db = drv.DB()
}
// Register DB stats to meter
if enableMetrics {
err = otelsql.RegisterDBStatsMetrics(db, otelsql.WithAttributes(
driverNameToSemConvKeyValue(driverName),
))
if err != nil {
return nil, errors.New(fmt.Sprintf("failed register otel meter: %v", err))
}
}
return drv, nil
}这是一个核心函数,用于创建 Ent 框架的数据库驱动,支持以下功能:
- 参数:
driverName:数据库驱动名称(如 mysql、postgresql 等)dsn:数据源名称,包含数据库连接信息enableTrace:是否启用分布式追踪enableMetrics:是否启用指标收集
- 功能:
- 如果启用追踪,使用
otelsql.Open创建支持追踪的数据库连接 - 如果不启用追踪,直接使用
entSql.Open创建连接 - 如果启用指标收集,注册数据库统计指标到 OpenTelemetry 仪表
- 返回创建的 Ent SQL 驱动
- 如果启用追踪,使用
1.10 总结
这个文件主要提供了对 Ent 框架数据库操作的封装,具有以下特点:
- 使用泛型实现了对不同类型数据库客户端的支持
- 提供了标准的数据库操作方法
- 支持连接池配置
- 集成了 OpenTelemetry 进行分布式追踪和指标收集
- 提供了驱动创建功能,支持多种数据库类型
这个工具类可以简化使用 Ent 框架进行数据库操作的代码,并提供了可观测性支持。