Skip to content
0

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:是否启用指标收集
  • 功能:
    1. 如果启用追踪,使用 otelsql.Open 创建支持追踪的数据库连接
    2. 如果不启用追踪,直接使用 entSql.Open 创建连接
    3. 如果启用指标收集,注册数据库统计指标到 OpenTelemetry 仪表
    4. 返回创建的 Ent SQL 驱动

1.10 总结

这个文件主要提供了对 Ent 框架数据库操作的封装,具有以下特点:

  1. 使用泛型实现了对不同类型数据库客户端的支持
  2. 提供了标准的数据库操作方法
  3. 支持连接池配置
  4. 集成了 OpenTelemetry 进行分布式追踪和指标收集
  5. 提供了驱动创建功能,支持多种数据库类型

这个工具类可以简化使用 Ent 框架进行数据库操作的代码,并提供了可观测性支持。

最近更新