804 lines
19 KiB
Markdown
804 lines
19 KiB
Markdown
# 工厂工具文档
|
||
|
||
## 概述
|
||
|
||
工厂工具提供了从配置直接创建已初始化客户端对象的功能,并提供了黑盒模式的便捷方法,让调用方无需关心底层实现细节,大大降低业务复杂度。
|
||
|
||
## 功能特性
|
||
|
||
- **黑盒模式**:提供直接调用的方法,无需获取客户端对象
|
||
- **延迟初始化**:所有客户端在首次使用时才创建
|
||
- **自动选择**:存储类型(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)` |
|
||
| **日期时间** | `Now()`, `ParseDateTime()`, `FormatDateTime()` 等 | `fac.Now("Asia/Shanghai")` |
|
||
| **金额计算** | `YuanToCents()`, `CentsToYuan()`, `FormatYuan()` | `fac.YuanToCents(100.5)` |
|
||
| **版本信息** | `GetVersion()` | `fac.GetVersion()` |
|
||
| **HTTP响应** | `Success()`, `Error()`, `SuccessPage()` | `fac.Success(w, data)` |
|
||
| **HTTP请求** | `ParseJSON()`, `GetQuery()`, `GetTimezone()` 等 | `fac.ParseJSON(r, &req)` |
|
||
|
||
### 🔧 高级功能:Get方法(仅在必要时使用)
|
||
|
||
返回客户端对象,用于复杂操作:
|
||
|
||
| 方法 | 返回类型 | 使用场景 |
|
||
|------|----------|----------|
|
||
| `GetDatabase()` | `*gorm.DB` | 数据库复杂查询、事务、关联查询等 |
|
||
| `GetRedisClient()` | `*redis.Client` | Hash、List、Set、ZSet、Pub/Sub等高级操作 |
|
||
| `GetLogger()` | `*logger.Logger` | Close()、设置全局logger等 |
|
||
|
||
## 使用方法
|
||
|
||
### 1. 创建工厂(推荐)
|
||
|
||
```go
|
||
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. 日志记录(黑盒模式,推荐)
|
||
|
||
```go
|
||
// 简单日志
|
||
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. 邮件发送(黑盒模式,推荐)
|
||
|
||
```go
|
||
// 简单邮件
|
||
err := fac.SendEmail(
|
||
[]string{"user@example.com"},
|
||
"验证码",
|
||
"您的验证码是:123456",
|
||
)
|
||
|
||
// HTML邮件
|
||
err := fac.SendEmail(
|
||
[]string{"user@example.com"},
|
||
"验证码",
|
||
"纯文本内容",
|
||
"<h1>HTML内容</h1>",
|
||
)
|
||
```
|
||
|
||
### 4. 短信发送(黑盒模式,推荐)
|
||
|
||
```go
|
||
// 使用配置中的模板代码
|
||
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. 文件上传和查看(黑盒模式,推荐)
|
||
|
||
```go
|
||
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操作(黑盒模式,推荐)
|
||
|
||
```go
|
||
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. 数据库操作(黑盒模式)
|
||
|
||
```go
|
||
// 获取数据库对象(已初始化,黑盒模式)
|
||
db, err := fac.GetDatabase()
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
// 直接使用GORM,无需自己实现创建逻辑
|
||
var users []User
|
||
db.Find(&users)
|
||
db.Create(&user)
|
||
```
|
||
|
||
### 8. 日期时间操作(黑盒模式)
|
||
|
||
```go
|
||
// 获取当前时间
|
||
now := fac.Now("Asia/Shanghai")
|
||
|
||
// 解析时间
|
||
t, _ := fac.ParseDateTime("2024-01-01 12:00:00", "Asia/Shanghai")
|
||
|
||
// 格式化时间
|
||
str := fac.FormatDateTime(now)
|
||
|
||
// 时间计算
|
||
tomorrow := fac.AddDays(now, 1)
|
||
startOfDay := fac.StartOfDay(now, "Asia/Shanghai")
|
||
endOfDay := fac.EndOfDay(now, "Asia/Shanghai")
|
||
|
||
// Unix时间戳
|
||
unix := fac.ToUnix(now)
|
||
t2 := fac.FromUnix(unix, "Asia/Shanghai")
|
||
```
|
||
|
||
### 9. 金额计算(黑盒模式)
|
||
|
||
```go
|
||
// 元转分
|
||
cents := fac.YuanToCents(100.5) // 10050
|
||
|
||
// 分转元
|
||
yuan := fac.CentsToYuan(10050) // 100.5
|
||
|
||
// 格式化显示
|
||
str := fac.FormatYuan(10050) // "100.50"
|
||
```
|
||
|
||
### 10. 版本信息(黑盒模式)
|
||
|
||
```go
|
||
version := fac.GetVersion()
|
||
fmt.Println("当前版本:", version)
|
||
```
|
||
|
||
### 11. HTTP响应(黑盒模式)
|
||
|
||
```go
|
||
import "net/http"
|
||
|
||
// 成功响应
|
||
fac.Success(w, data)
|
||
fac.Success(w, data, "操作成功")
|
||
|
||
// 分页响应
|
||
fac.SuccessPage(w, users, total, page, pageSize)
|
||
|
||
// 错误响应
|
||
fac.Error(w, 1001, "用户不存在")
|
||
fac.SystemError(w, "系统错误")
|
||
```
|
||
|
||
### 12. HTTP请求解析(黑盒模式)
|
||
|
||
```go
|
||
import "net/http"
|
||
|
||
// 解析JSON
|
||
var req UserRequest
|
||
fac.ParseJSON(r, &req)
|
||
|
||
// 获取查询参数
|
||
id := fac.GetQueryInt64(r, "id", 0)
|
||
keyword := fac.GetQuery(r, "keyword", "")
|
||
|
||
// 获取时区(需要配合middleware.Timezone使用)
|
||
timezone := fac.GetTimezone(r)
|
||
```
|
||
|
||
### 13. Redis操作(获取客户端对象)
|
||
|
||
```go
|
||
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()
|
||
```
|
||
|
||
|
||
## 完整示例
|
||
|
||
```go
|
||
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
|
||
|
||
获取配置对象。
|
||
|
||
**返回:** 配置对象
|
||
|
||
### HTTP响应方法(黑盒模式)
|
||
|
||
#### Success(w http.ResponseWriter, data interface{}, message ...string)
|
||
|
||
发送成功响应。
|
||
|
||
**参数:**
|
||
- `w`: HTTP响应写入器
|
||
- `data`: 响应数据
|
||
- `message`: 可选,成功消息(如果不提供,使用默认消息)
|
||
|
||
**示例:**
|
||
```go
|
||
fac.Success(w, user) // 使用默认消息
|
||
fac.Success(w, user, "获取成功") // 自定义消息
|
||
```
|
||
|
||
#### Error(w http.ResponseWriter, code int, message string)
|
||
|
||
发送错误响应。
|
||
|
||
**参数:**
|
||
- `w`: HTTP响应写入器
|
||
- `code`: 业务错误码
|
||
- `message`: 错误消息
|
||
|
||
#### SystemError(w http.ResponseWriter, message string)
|
||
|
||
发送系统错误响应(HTTP 500)。
|
||
|
||
**参数:**
|
||
- `w`: HTTP响应写入器
|
||
- `message`: 错误消息
|
||
|
||
#### SuccessPage(w http.ResponseWriter, data interface{}, total int64, page, pageSize int, message ...string)
|
||
|
||
发送分页成功响应。
|
||
|
||
**参数:**
|
||
- `w`: HTTP响应写入器
|
||
- `data`: 响应数据列表
|
||
- `total`: 总记录数
|
||
- `page`: 当前页码
|
||
- `pageSize`: 每页大小
|
||
- `message`: 可选,成功消息
|
||
|
||
### HTTP请求方法(黑盒模式)
|
||
|
||
#### ParseJSON(r *http.Request, v interface{}) error
|
||
|
||
解析JSON请求体。
|
||
|
||
**参数:**
|
||
- `r`: HTTP请求
|
||
- `v`: 目标结构体指针
|
||
|
||
#### GetQuery(r *http.Request, key, defaultValue string) string
|
||
|
||
获取查询参数。
|
||
|
||
#### GetQueryInt(r *http.Request, key string, defaultValue int) int
|
||
|
||
获取查询整数参数。
|
||
|
||
#### GetQueryInt64(r *http.Request, key string, defaultValue int64) int64
|
||
|
||
获取查询64位整数参数。
|
||
|
||
#### GetFormValue(r *http.Request, key, defaultValue string) string
|
||
|
||
获取表单值。
|
||
|
||
#### GetTimezone(r *http.Request) string
|
||
|
||
从请求的context中获取时区(需要配合middleware.Timezone使用)。
|
||
|
||
### 日期时间工具方法(黑盒模式)
|
||
|
||
#### Now(timezone ...string) time.Time
|
||
|
||
获取当前时间。
|
||
|
||
**参数:**
|
||
- `timezone`: 可选,时区字符串(如 "Asia/Shanghai"),不指定则使用默认时区
|
||
|
||
#### ParseDateTime(value string, timezone ...string) (time.Time, error)
|
||
|
||
解析日期时间字符串(格式:2006-01-02 15:04:05)。
|
||
|
||
#### ParseDate(value string, timezone ...string) (time.Time, error)
|
||
|
||
解析日期字符串(格式:2006-01-02)。
|
||
|
||
#### FormatDateTime(t time.Time, timezone ...string) string
|
||
|
||
格式化日期时间(格式:2006-01-02 15:04:05)。
|
||
|
||
#### FormatDate(t time.Time, timezone ...string) string
|
||
|
||
格式化日期(格式:2006-01-02)。
|
||
|
||
#### FormatTime(t time.Time, timezone ...string) string
|
||
|
||
格式化时间(格式:15:04:05)。
|
||
|
||
#### ToUnix(t time.Time) int64
|
||
|
||
转换为Unix时间戳(秒)。
|
||
|
||
#### FromUnix(sec int64, timezone ...string) time.Time
|
||
|
||
从Unix时间戳创建时间。
|
||
|
||
#### ToUnixMilli(t time.Time) int64
|
||
|
||
转换为Unix毫秒时间戳。
|
||
|
||
#### FromUnixMilli(msec int64, timezone ...string) time.Time
|
||
|
||
从Unix毫秒时间戳创建时间。
|
||
|
||
#### AddDays(t time.Time, days int) time.Time
|
||
|
||
添加天数。
|
||
|
||
#### AddMonths(t time.Time, months int) time.Time
|
||
|
||
添加月数。
|
||
|
||
#### AddYears(t time.Time, years int) time.Time
|
||
|
||
添加年数。
|
||
|
||
#### StartOfDay(t time.Time, timezone ...string) time.Time
|
||
|
||
获取一天的开始时间(00:00:00)。
|
||
|
||
#### EndOfDay(t time.Time, timezone ...string) time.Time
|
||
|
||
获取一天的结束时间(23:59:59.999999999)。
|
||
|
||
#### StartOfMonth(t time.Time, timezone ...string) time.Time
|
||
|
||
获取月份的开始时间。
|
||
|
||
#### EndOfMonth(t time.Time, timezone ...string) time.Time
|
||
|
||
获取月份的结束时间。
|
||
|
||
#### StartOfYear(t time.Time, timezone ...string) time.Time
|
||
|
||
获取年份的开始时间。
|
||
|
||
#### EndOfYear(t time.Time, timezone ...string) time.Time
|
||
|
||
获取年份的结束时间。
|
||
|
||
#### DiffDays(t1, t2 time.Time) int
|
||
|
||
计算两个时间之间的天数差。
|
||
|
||
#### DiffHours(t1, t2 time.Time) int64
|
||
|
||
计算两个时间之间的小时差。
|
||
|
||
#### DiffMinutes(t1, t2 time.Time) int64
|
||
|
||
计算两个时间之间的分钟差。
|
||
|
||
#### DiffSeconds(t1, t2 time.Time) int64
|
||
|
||
计算两个时间之间的秒数差。
|
||
|
||
### 金额工具方法(黑盒模式)
|
||
|
||
#### GetMoneyCalculator() *tools.MoneyCalculator
|
||
|
||
获取金额计算器实例。
|
||
|
||
#### YuanToCents(yuan float64) int64
|
||
|
||
元转分。
|
||
|
||
**示例:**
|
||
```go
|
||
cents := fac.YuanToCents(100.5) // 返回 10050
|
||
```
|
||
|
||
#### CentsToYuan(cents int64) float64
|
||
|
||
分转元。
|
||
|
||
**示例:**
|
||
```go
|
||
yuan := fac.CentsToYuan(10050) // 返回 100.5
|
||
```
|
||
|
||
#### FormatYuan(cents int64) string
|
||
|
||
格式化显示金额(分转元,保留2位小数)。
|
||
|
||
**示例:**
|
||
```go
|
||
str := fac.FormatYuan(10050) // 返回 "100.50"
|
||
```
|
||
|
||
### 版本工具方法(黑盒模式)
|
||
|
||
#### GetVersion() string
|
||
|
||
获取版本号。
|
||
|
||
**说明:**
|
||
- 优先从环境变量 `DOCKER_TAG` 或 `VERSION` 中读取
|
||
- 如果没有设置环境变量,则使用默认版本号
|
||
|
||
## 设计优势
|
||
|
||
### 优势总结
|
||
|
||
1. **降低复杂度**:调用方无需关心客户端对象的创建和管理
|
||
2. **延迟初始化**:所有客户端在首次使用时才创建,提高性能
|
||
3. **自动选择**:存储类型根据配置自动选择,无需手动指定
|
||
4. **统一接口**:所有操作通过工厂方法调用,接口统一
|
||
5. **容错处理**:日志初始化失败时自动回退到标准输出
|
||
6. **代码简洁**:只提供黑盒模式方法,保持代码简洁清晰
|
||
|
||
## 注意事项
|
||
|
||
1. **配置检查**:工厂方法会自动检查配置是否存在,如果配置为nil会返回错误
|
||
2. **错误处理**:所有方法都可能返回错误,需要正确处理
|
||
3. **延迟初始化**:所有客户端在首次使用时才创建,首次调用可能稍慢
|
||
4. **存储选择**:存储类型根据配置自动选择(优先级:MinIO > OSS)
|
||
5. **数据库对象**:数据库保持返回GORM对象,因为GORM已经提供了很好的抽象
|
||
6. **黑盒模式**:所有功能都通过工厂方法直接调用,无需获取底层客户端对象
|
||
|
||
## 示例
|
||
|
||
完整示例请参考 `examples/factory_example.go`
|