Files
go-common/docs/factory.md
2025-12-05 00:07:15 +08:00

13 KiB
Raw Permalink Blame History

工厂工具文档

概述

工厂工具提供了从配置直接创建已初始化客户端对象的功能,并提供了黑盒模式的便捷方法,让调用方无需关心底层实现细节,大大降低业务复杂度。

功能特性

  • 黑盒模式:提供直接调用的方法,无需获取客户端对象
  • 延迟初始化:所有客户端在首次使用时才创建
  • 自动选择存储类型OSS/MinIO根据配置自动选择
  • 统一接口:所有操作通过工厂方法调用
  • 向后兼容:保留 GetXXX() 方法,需要时可获取对象

方法分类总览

🌟 推荐使用:黑盒方法(一行代码搞定)

外部项目直接调用,无需获取内部对象:

功能 方法 示例
中间件 GetMiddlewareChain() chain := fac.GetMiddlewareChain()
日志 LogInfo(), LogError() fac.LogInfo("用户登录")
Redis RedisSet(), RedisGet() fac.RedisSet(ctx, "key", "val", time.Hour)
邮件 SendEmail() fac.SendEmail(to, subject, body)
短信 SendSMS() fac.SendSMS(phones, params)
存储 UploadFile(), GetFileURL() fac.UploadFile(ctx, key, file)

🔧 高级功能Get方法仅在必要时使用

返回客户端对象,用于复杂操作:

方法 返回类型 使用场景
GetDatabase() *gorm.DB 数据库复杂查询、事务、关联查询等
GetRedisClient() *redis.Client Hash、List、Set、ZSet、Pub/Sub等高级操作
GetLogger() *logger.Logger Close()、设置全局logger等

使用方法

1. 创建工厂(推荐)

import "git.toowon.com/jimmy/go-common/factory"

// 方式1直接从配置文件创建最推荐
fac, err := factory.NewFactoryFromFile("./config.json")
if err != nil {
    log.Fatal(err)
}

// 方式2从配置对象创建
cfg, _ := config.LoadFromFile("./config.json")
fac := factory.NewFactory(cfg)

2. 日志记录(黑盒模式,推荐)

// 简单日志
fac.LogDebug("调试信息: %s", "test")
fac.LogInfo("用户登录成功")
fac.LogWarn("警告信息")
fac.LogError("错误信息: %v", err)

// 带字段的日志
fac.LogInfof(map[string]interface{}{
    "user_id": 123,
    "ip": "192.168.1.1",
}, "用户登录成功")

fac.LogErrorf(map[string]interface{}{
    "error_code": 1001,
}, "登录失败: %v", err)

3. 邮件发送(黑盒模式,推荐)

// 简单邮件
err := fac.SendEmail(
    []string{"user@example.com"},
    "验证码",
    "您的验证码是123456",
)

// HTML邮件
err := fac.SendEmail(
    []string{"user@example.com"},
    "验证码",
    "纯文本内容",
    "<h1>HTML内容</h1>",
)

4. 短信发送(黑盒模式,推荐)

// 使用配置中的模板代码
resp, err := fac.SendSMS(
    []string{"13800138000"},
    map[string]string{"code": "123456"},
)

// 指定模板代码
resp, err := fac.SendSMS(
    []string{"13800138000"},
    map[string]string{"code": "123456"},
    "SMS_123456789", // 模板代码
)

5. 文件上传和查看(黑盒模式,推荐)

import (
    "context"
    "os"
)

ctx := context.Background()

// 上传文件自动选择OSS或MinIO
file, _ := os.Open("test.jpg")
defer file.Close()

url, err := fac.UploadFile(ctx, "images/test.jpg", file, "image/jpeg")
if err != nil {
    log.Fatal(err)
}
fmt.Println("文件URL:", url)

// 获取文件URL永久有效
url, _ := fac.GetFileURL("images/test.jpg", 0)

// 获取临时访问URL1小时后过期
url, _ := fac.GetFileURL("images/test.jpg", 3600)

6. Redis操作黑盒模式推荐

import "context"

ctx := context.Background()

// 设置值(不过期)
err := fac.RedisSet(ctx, "user:123", "value")

// 设置值(带过期时间)
err := fac.RedisSet(ctx, "user:123", "value", time.Hour)

// 获取值
value, err := fac.RedisGet(ctx, "user:123")

// 删除键
err := fac.RedisDelete(ctx, "user:123", "user:456")

// 检查键是否存在
exists, err := fac.RedisExists(ctx, "user:123")

7. 数据库操作(黑盒模式)

// 获取数据库对象(已初始化,黑盒模式)
db, err := fac.GetDatabase()
if err != nil {
    log.Fatal(err)
}

// 直接使用GORM无需自己实现创建逻辑
var users []User
db.Find(&users)
db.Create(&user)

8. Redis操作获取客户端对象

import (
    "context"
    "github.com/redis/go-redis/v9"
)

ctx := context.Background()

// 获取Redis客户端对象已初始化黑盒模式
redisClient, err := fac.GetRedisClient()
if err != nil {
    log.Fatal(err)
}

// 直接使用Redis客户端无需自己实现创建逻辑
val, err := redisClient.Get(ctx, "key").Result()
if err != nil && err != redis.Nil {
    log.Printf("Redis error: %v", err)
} else if err == redis.Nil {
    fmt.Println("Key not found")
} else {
    fmt.Printf("Value: %s\n", val)
}

// 使用高级功能如Hash操作
redisClient.HSet(ctx, "user:123", "name", "John")
name, _ := redisClient.HGet(ctx, "user:123", "name").Result()

完整示例

package main

import (
    "context"
    "log"
    "os"
    "time"

    "git.toowon.com/jimmy/go-common/factory"
)

func main() {
    // 创建工厂
    fac, err := factory.NewFactoryFromFile("./config.json")
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // 日志记录(黑盒模式)
    fac.LogInfo("应用启动")
    fac.LogInfof(map[string]interface{}{
        "version": "1.0.0",
    }, "应用启动成功")

    // 邮件发送(黑盒模式)
    err = fac.SendEmail(
        []string{"user@example.com"},
        "欢迎",
        "欢迎使用我们的服务",
    )
    if err != nil {
        fac.LogError("发送邮件失败: %v", err)
    }

    // 短信发送(黑盒模式)
    resp, err := fac.SendSMS(
        []string{"13800138000"},
        map[string]string{"code": "123456"},
    )
    if err != nil {
        fac.LogError("发送短信失败: %v", err)
    } else {
        fac.LogInfo("短信发送成功: %s", resp.RequestID)
    }

    // 文件上传黑盒模式自动选择OSS或MinIO
    file, _ := os.Open("test.jpg")
    defer file.Close()

    url, err := fac.UploadFile(ctx, "images/test.jpg", file, "image/jpeg")
    if err != nil {
        fac.LogError("上传文件失败: %v", err)
    } else {
        fac.LogInfo("文件上传成功: %s", url)
    }

    // Redis操作黑盒模式
    err = fac.RedisSet(ctx, "user:123", "value", time.Hour)
    if err != nil {
        fac.LogError("Redis设置失败: %v", err)
    }

    value, err := fac.RedisGet(ctx, "user:123")
    if err != nil {
        fac.LogError("Redis获取失败: %v", err)
    } else {
        fac.LogInfo("Redis值: %s", value)
    }

    // 数据库操作
    db, err := fac.GetDatabase()
    if err != nil {
        fac.LogError("数据库连接失败: %v", err)
    } else {
        var count int64
        db.Table("users").Count(&count)
        fac.LogInfo("用户数量: %d", count)
    }
}

API 参考

工厂创建

NewFactory(cfg *config.Config) *Factory

创建工厂实例。

参数:

  • cfg: 配置对象

返回: 工厂实例

NewFactoryFromFile(filePath string) (*Factory, error)

从配置文件直接创建工厂实例(便捷方法)。

参数:

  • filePath: 配置文件路径

返回: 工厂实例和错误信息

说明: 这是推荐的使用方式,一步完成配置加载和工厂创建。

日志方法(黑盒模式)

LogDebug(message string, args ...interface{})

记录调试日志。

LogDebugf(fields map[string]interface{}, message string, args ...interface{})

记录调试日志(带字段)。

LogInfo(message string, args ...interface{})

记录信息日志。

LogInfof(fields map[string]interface{}, message string, args ...interface{})

记录信息日志(带字段)。

LogWarn(message string, args ...interface{})

记录警告日志。

LogWarnf(fields map[string]interface{}, message string, args ...interface{})

记录警告日志(带字段)。

LogError(message string, args ...interface{})

记录错误日志。

LogErrorf(fields map[string]interface{}, message string, args ...interface{})

记录错误日志(带字段)。

邮件方法(黑盒模式)

SendEmail(to []string, subject, body string, htmlBody ...string) error

发送邮件。

参数:

  • to: 收件人列表
  • subject: 邮件主题
  • body: 邮件正文(纯文本)
  • htmlBody: HTML正文可选如果设置了会优先使用

短信方法(黑盒模式)

SendSMS(phoneNumbers []string, templateParam interface{}, templateCode ...string) (*sms.SendResponse, error)

发送短信。

参数:

  • phoneNumbers: 手机号列表
  • templateParam: 模板参数map或JSON字符串
  • templateCode: 模板代码(可选,如果为空使用配置中的模板代码)

存储方法(黑盒模式)

UploadFile(ctx context.Context, objectKey string, reader io.Reader, contentType ...string) (string, error)

上传文件。

参数:

  • ctx: 上下文
  • objectKey: 对象键(文件路径)
  • reader: 文件内容
  • contentType: 文件类型(可选)

返回: 文件访问URL和错误信息

说明: 自动根据配置选择OSS或MinIO优先级MinIO > OSS

GetFileURL(objectKey string, expires int64) (string, error)

获取文件访问URL。

参数:

  • objectKey: 对象键
  • expires: 过期时间0表示永久有效

返回: 文件访问URL和错误信息

Redis方法黑盒模式

RedisGet(ctx context.Context, key string) (string, error)

获取Redis值。

参数:

  • ctx: 上下文
  • key: Redis键

返回: 值和错误信息key不存在时返回空字符串

RedisSet(ctx context.Context, key string, value interface{}, expiration ...time.Duration) error

设置Redis值。

参数:

  • ctx: 上下文
  • key: Redis键
  • value: Redis值
  • expiration: 过期时间可选0表示不过期

RedisDelete(ctx context.Context, keys ...string) error

删除Redis键。

参数:

  • ctx: 上下文
  • keys: Redis键列表

RedisExists(ctx context.Context, key string) (bool, error)

检查Redis键是否存在。

参数:

  • ctx: 上下文
  • key: Redis键

返回: 是否存在和错误信息

数据库方法

GetDatabase() (*gorm.DB, error)

获取数据库连接对象(已初始化)。

返回: 已初始化的GORM数据库对象和错误信息

说明:

  • 支持MySQL、PostgreSQL、SQLite
  • 自动配置连接池参数
  • 数据库时间统一使用UTC时区
  • 延迟初始化,首次调用时创建连接
  • 黑盒模式只需传递config对象无需自己实现创建逻辑

Redis方法

GetRedisClient() (*redis.Client, error)

获取Redis客户端对象已初始化

返回: 已初始化的Redis客户端对象和错误信息

说明:

  • 自动处理所有配置检查和连接测试
  • 自动设置默认值(连接池大小、超时时间等)
  • 连接失败时会自动关闭客户端并返回错误
  • 返回的客户端已通过Ping测试可直接使用
  • 黑盒模式只需传递config对象无需自己实现创建逻辑
  • 推荐使用 RedisGetRedisSetRedisDelete 等方法直接操作Redis
  • 如果需要使用Redis的高级功能如Hash、List、Set等可以使用此方法获取客户端对象

配置方法

GetConfig() *config.Config

获取配置对象。

返回: 配置对象

设计优势

优势总结

  1. 降低复杂度:调用方无需关心客户端对象的创建和管理
  2. 延迟初始化:所有客户端在首次使用时才创建,提高性能
  3. 自动选择:存储类型根据配置自动选择,无需手动指定
  4. 统一接口:所有操作通过工厂方法调用,接口统一
  5. 容错处理:日志初始化失败时自动回退到标准输出
  6. 代码简洁:只提供黑盒模式方法,保持代码简洁清晰

注意事项

  1. 配置检查工厂方法会自动检查配置是否存在如果配置为nil会返回错误
  2. 错误处理:所有方法都可能返回错误,需要正确处理
  3. 延迟初始化:所有客户端在首次使用时才创建,首次调用可能稍慢
  4. 存储选择存储类型根据配置自动选择优先级MinIO > OSS
  5. 数据库对象数据库保持返回GORM对象因为GORM已经提供了很好的抽象
  6. 黑盒模式:所有功能都通过工厂方法直接调用,无需获取底层客户端对象

示例

完整示例请参考 examples/factory_example.go