13 KiB
13 KiB
工厂工具文档
概述
工厂工具提供了从配置直接创建已初始化客户端对象的功能,并提供了黑盒模式的便捷方法,让调用方无需关心底层实现细节,大大降低业务复杂度。
功能特性
- 黑盒模式:提供直接调用的方法,无需获取客户端对象
- 延迟初始化:所有客户端在首次使用时才创建
- 自动选择:存储类型(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)
// 获取临时访问URL(1小时后过期)
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对象,无需自己实现创建逻辑
- 推荐使用
RedisGet、RedisSet、RedisDelete等方法直接操作Redis - 如果需要使用Redis的高级功能(如Hash、List、Set等),可以使用此方法获取客户端对象
配置方法
GetConfig() *config.Config
获取配置对象。
返回: 配置对象
设计优势
优势总结
- 降低复杂度:调用方无需关心客户端对象的创建和管理
- 延迟初始化:所有客户端在首次使用时才创建,提高性能
- 自动选择:存储类型根据配置自动选择,无需手动指定
- 统一接口:所有操作通过工厂方法调用,接口统一
- 容错处理:日志初始化失败时自动回退到标准输出
- 代码简洁:只提供黑盒模式方法,保持代码简洁清晰
注意事项
- 配置检查:工厂方法会自动检查配置是否存在,如果配置为nil会返回错误
- 错误处理:所有方法都可能返回错误,需要正确处理
- 延迟初始化:所有客户端在首次使用时才创建,首次调用可能稍慢
- 存储选择:存储类型根据配置自动选择(优先级:MinIO > OSS)
- 数据库对象:数据库保持返回GORM对象,因为GORM已经提供了很好的抽象
- 黑盒模式:所有功能都通过工厂方法直接调用,无需获取底层客户端对象
示例
完整示例请参考 examples/factory_example.go