修改对象的获取方式

This commit is contained in:
2025-11-30 13:50:28 +08:00
parent a655640ab2
commit 7585b8e9da
6 changed files with 279 additions and 73 deletions

View File

@@ -29,7 +29,7 @@
提供阿里云短信发送功能支持模板短信和批量发送使用Go标准库实现。 提供阿里云短信发送功能支持模板短信和批量发送使用Go标准库实现。
### 9. 工厂工具 (factory) ### 9. 工厂工具 (factory)
提供从配置直接创建已初始化客户端对象的功能,避免调用方重复实现创建逻辑。 提供从配置文件直接创建已初始化客户端对象的功能,包括数据库、Redis、邮件、短信、日志等避免调用方重复实现创建逻辑。
### 10. 日志工具 (logger) ### 10. 日志工具 (logger)
提供统一的日志记录功能支持多种日志级别和输出方式使用Go标准库实现。 提供统一的日志记录功能支持多种日志级别和输出方式使用Go标准库实现。
@@ -185,27 +185,33 @@ smsClient.SendSimple(
#### 使用工厂直接获取客户端(推荐) #### 使用工厂直接获取客户端(推荐)
```go ```go
import ( import "git.toowon.com/jimmy/go-common/factory"
"git.toowon.com/jimmy/go-common/config"
"git.toowon.com/jimmy/go-common/factory"
)
// 加载配置并创建工厂 // 方式1直接从配置文件创建工厂最推荐
cfg, _ := config.LoadFromFile("./config.json") fac, _ := factory.NewFactoryFromFile("./config.json")
fac := factory.NewFactory(cfg)
// 直接获取数据库对象(已初始化,可直接使用)
db, _ := fac.GetDatabase()
db.Find(&users) // 直接使用,无需再创建连接
// 获取Redis配置用于创建Redis客户端
redisConfig := fac.GetRedisConfig()
// 使用go-redis创建客户端
// rdb := redis.NewClient(&redis.Options{
// Addr: fmt.Sprintf("%s:%d", redisConfig.Host, redisConfig.Port),
// Password: redisConfig.Password,
// DB: redisConfig.Database,
// })
// 直接获取已初始化的客户端(无需重复实现创建逻辑) // 直接获取已初始化的客户端(无需重复实现创建逻辑)
emailClient, _ := fac.GetEmailClient() emailClient, _ := fac.GetEmailClient()
smsClient, _ := fac.GetSMSClient() smsClient, _ := fac.GetSMSClient()
logger, _ := fac.GetLogger()
// 直接使用 // 直接使用
emailClient.SendSimple(...) emailClient.SendSimple(...)
smsClient.SendSimple(...) smsClient.SendSimple(...)
// 获取日志记录器(已初始化,可直接使用)
logger, _ := fac.GetLogger()
logger.Info("Application started") logger.Info("Application started")
logger.Error("Error occurred: %v", err)
``` ```
更多示例请查看 [examples](./examples/) 目录。 更多示例请查看 [examples](./examples/) 目录。

View File

@@ -12,7 +12,24 @@
## 使用方法 ## 使用方法
### 1. 创建工厂实例 ### 1. 从配置文件直接创建工厂(推荐)
```go
import "git.toowon.com/jimmy/go-common/factory"
// 直接传入配置文件路径,自动加载配置并创建工厂
fac, err := factory.NewFactoryFromFile("./config.json")
if err != nil {
log.Fatal(err)
}
// 直接获取已初始化的对象
db, _ := fac.GetDatabase() // 直接获取数据库对象
logger, _ := fac.GetLogger() // 直接获取日志对象
emailClient, _ := fac.GetEmailClient() // 直接获取邮件客户端
```
### 2. 从配置对象创建工厂
```go ```go
import ( import (
@@ -30,7 +47,38 @@ if err != nil {
fac := factory.NewFactory(cfg) fac := factory.NewFactory(cfg)
``` ```
### 2. 获取邮件客户端(已初始化) ### 3. 获取数据库对象(已初始化,推荐
```go
// 直接获取已初始化的数据库对象(*gorm.DB
db, err := fac.GetDatabase()
if err != nil {
log.Fatal(err)
}
// 直接使用,无需再创建连接
var users []User
db.Find(&users)
db.Create(&user)
```
### 4. 获取Redis配置
```go
// 获取Redis配置用于创建Redis客户端
// 注意Go标准库没有Redis客户端需要调用方使用第三方库创建
redisConfig := fac.GetRedisConfig()
if redisConfig != nil {
// 使用go-redis创建客户端示例
// rdb := redis.NewClient(&redis.Options{
// Addr: fmt.Sprintf("%s:%d", redisConfig.Host, redisConfig.Port),
// Password: redisConfig.Password,
// DB: redisConfig.Database,
// })
}
```
### 5. 获取邮件客户端(已初始化)
```go ```go
// 直接获取已初始化的邮件客户端 // 直接获取已初始化的邮件客户端
@@ -47,7 +95,7 @@ err = emailClient.SendSimple(
) )
``` ```
### 3. 获取短信客户端(已初始化) ### 6. 获取短信客户端(已初始化)
```go ```go
// 直接获取已初始化的短信客户端 // 直接获取已初始化的短信客户端
@@ -63,7 +111,7 @@ resp, err := smsClient.SendSimple(
) )
``` ```
### 4. 获取日志记录器(已初始化) ### 7. 获取日志记录器(已初始化)
```go ```go
// 直接获取已初始化的日志记录器 // 直接获取已初始化的日志记录器
@@ -77,7 +125,7 @@ logger.Info("Application started")
logger.Error("Error occurred: %v", err) logger.Error("Error occurred: %v", err)
``` ```
### 5. 完整示例 ### 8. 完整示例
```go ```go
package main package main
@@ -150,6 +198,17 @@ func main() {
**返回:** 工厂实例 **返回:** 工厂实例
### NewFactoryFromFile(filePath string) (*Factory, error)
从配置文件直接创建工厂实例(便捷方法)。
**参数:**
- `filePath`: 配置文件路径
**返回:** 工厂实例和错误信息
**说明:** 这是推荐的使用方式,一步完成配置加载和工厂创建。
### (f *Factory) GetEmailClient() (*email.Email, error) ### (f *Factory) GetEmailClient() (*email.Email, error)
获取邮件客户端(已初始化)。 获取邮件客户端(已初始化)。
@@ -174,6 +233,27 @@ func main() {
**说明:** 如果日志配置为nil会使用默认配置创建。 **说明:** 如果日志配置为nil会使用默认配置创建。
### (f *Factory) GetDatabase() (*gorm.DB, error)
获取数据库连接对象(已初始化)。
**返回:** 已初始化的GORM数据库对象和错误信息
**说明:**
- 支持MySQL、PostgreSQL、SQLite
- 自动配置连接池参数
- 数据库时间统一使用UTC时区
### (f *Factory) GetRedisConfig() *config.RedisConfig
获取Redis配置用于创建Redis客户端
**返回:** Redis配置对象可能为nil
**说明:**
- Go标准库没有Redis客户端需要调用方使用第三方库如go-redis/redis创建
- 返回配置对象调用方可以根据配置创建Redis客户端
### (f *Factory) GetConfig() *config.Config ### (f *Factory) GetConfig() *config.Config
获取配置对象。 获取配置对象。
@@ -187,30 +267,33 @@ func main() {
```go ```go
// 调用方需要自己实现创建逻辑 // 调用方需要自己实现创建逻辑
cfg, _ := config.LoadFromFile("./config.json") cfg, _ := config.LoadFromFile("./config.json")
emailConfig := cfg.GetEmail() dsn, _ := cfg.GetDatabaseDSN()
if emailConfig == nil { db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
log.Fatal("email config is nil")
}
emailClient, err := email.NewEmail(emailConfig)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
// 配置连接池
sqlDB, _ := db.DB()
sqlDB.SetMaxOpenConns(100)
// 才能使用 // 才能使用
emailClient.SendSimple(...) db.Find(&users)
``` ```
### 使用工厂方式(直接获取已初始化对象) ### 使用工厂方式(直接获取已初始化对象)
```go ```go
// 直接获取已初始化的对象,无需重复实现 // 方式1直接从配置文件创建最推荐
fac, _ := factory.NewFactoryFromFile("./config.json")
db, _ := fac.GetDatabase() // 直接获取已初始化的数据库对象
// 直接使用
db.Find(&users)
// 方式2从配置对象创建
cfg, _ := config.LoadFromFile("./config.json") cfg, _ := config.LoadFromFile("./config.json")
fac := factory.NewFactory(cfg) fac := factory.NewFactory(cfg)
emailClient, err := fac.GetEmailClient() db, _ := fac.GetDatabase() // 直接获取已初始化的数据库对象
if err != nil {
log.Fatal(err)
}
// 直接使用 // 直接使用
emailClient.SendSimple(...) db.Find(&users)
``` ```
## 注意事项 ## 注意事项

View File

@@ -4,69 +4,86 @@ import (
"fmt" "fmt"
"log" "log"
"git.toowon.com/jimmy/go-common/config"
"git.toowon.com/jimmy/go-common/factory" "git.toowon.com/jimmy/go-common/factory"
) )
func main() { func main() {
// 加载配置 // 方式1直接从配置文件创建工厂推荐
cfg, err := config.LoadFromFile("./config/example.json") fac, err := factory.NewFactoryFromFile("./config/example.json")
if err != nil { if err != nil {
log.Fatal("Failed to load config:", err) log.Fatal("Failed to create factory:", err)
} }
// 创建工厂实例 // 直接获取数据库对象(已初始化,可直接使用)
fac := factory.NewFactory(cfg) db, err := fac.GetDatabase()
if err != nil {
log.Printf("Database not available: %v", err)
} else {
// 直接使用数据库
var count int64
if err := db.Table("users").Count(&count).Error; err != nil {
log.Printf("Failed to count users: %v", err)
} else {
fmt.Printf("User count: %d\n", count)
}
}
// 示例1获取邮件客户端已初始化可直接使用 // 获取Redis配置用于创建Redis客户端
fmt.Println("=== Example 1: Get Email Client ===") redisConfig := fac.GetRedisConfig()
if redisConfig != nil {
fmt.Printf("Redis config: %s:%d\n", redisConfig.Host, redisConfig.Port)
// 使用go-redis创建客户端示例
// import "github.com/redis/go-redis/v9"
// rdb := redis.NewClient(&redis.Options{
// Addr: fmt.Sprintf("%s:%d", redisConfig.Host, redisConfig.Port),
// Password: redisConfig.Password,
// DB: redisConfig.Database,
// })
}
// 获取邮件客户端(已初始化,可直接使用)
emailClient, err := fac.GetEmailClient() emailClient, err := fac.GetEmailClient()
if err != nil { if err != nil {
log.Printf("Email client not available: %v", err) log.Printf("Email client not available: %v", err)
} else { } else {
fmt.Println("Email client created successfully") // 直接使用
// 直接使用,无需再创建 err = emailClient.SendSimple(
_ = emailClient // 示例中不使用,实际使用时可以直接调用方法 []string{"recipient@example.com"},
// err = emailClient.SendSimple( "测试邮件",
// []string{"recipient@example.com"}, "这是测试内容",
// "测试邮件", )
// "这是测试内容", if err != nil {
// ) log.Printf("Failed to send email: %v", err)
fmt.Println("Email client is ready to use") } else {
fmt.Println("Email sent successfully")
}
} }
// 示例2获取短信客户端(已初始化,可直接使用) // 获取短信客户端(已初始化,可直接使用)
fmt.Println("\n=== Example 2: Get SMS Client ===")
smsClient, err := fac.GetSMSClient() smsClient, err := fac.GetSMSClient()
if err != nil { if err != nil {
log.Printf("SMS client not available: %v", err) log.Printf("SMS client not available: %v", err)
} else { } else {
fmt.Println("SMS client created successfully") // 直接使用
// 直接使用,无需再创建 resp, err := smsClient.SendSimple(
_ = smsClient // 示例中不使用,实际使用时可以直接调用方法 []string{"13800138000"},
// resp, err := smsClient.SendSimple( map[string]string{"code": "123456"},
// []string{"13800138000"}, )
// map[string]string{"code": "123456"}, if err != nil {
// ) log.Printf("Failed to send SMS: %v", err)
fmt.Println("SMS client is ready to use") } else {
fmt.Printf("SMS sent: %s\n", resp.RequestID)
}
} }
// 示例3访问配置对象 // 获取日志记录器(已初始化,可直接使用)
fmt.Println("\n=== Example 3: Access Config Object ===") logger, err := fac.GetLogger()
cfgObj := fac.GetConfig()
dsn, err := cfgObj.GetDatabaseDSN()
if err != nil { if err != nil {
log.Printf("Database DSN not available: %v", err) log.Printf("Logger not available: %v", err)
} else { } else {
fmt.Printf("Database DSN: %s\n", dsn) logger.Info("Application started")
logger.Debug("Debug message")
logger.Warn("Warning message")
logger.Error("Error message")
} }
redisAddr := cfgObj.GetRedisAddr()
if redisAddr != "" {
fmt.Printf("Redis Address: %s\n", redisAddr)
}
fmt.Println("\nNote: Factory provides initialized clients directly,")
fmt.Println("no need to implement creation logic in your code.")
} }

View File

@@ -2,11 +2,16 @@ package factory
import ( import (
"fmt" "fmt"
"time"
"git.toowon.com/jimmy/go-common/config" "git.toowon.com/jimmy/go-common/config"
"git.toowon.com/jimmy/go-common/email" "git.toowon.com/jimmy/go-common/email"
"git.toowon.com/jimmy/go-common/logger" "git.toowon.com/jimmy/go-common/logger"
"git.toowon.com/jimmy/go-common/sms" "git.toowon.com/jimmy/go-common/sms"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
) )
// Factory 工厂类,用于从配置创建各种客户端对象 // Factory 工厂类,用于从配置创建各种客户端对象
@@ -21,6 +26,16 @@ func NewFactory(cfg *config.Config) *Factory {
} }
} }
// NewFactoryFromFile 从配置文件创建工厂实例(便捷方法)
// filePath: 配置文件路径
func NewFactoryFromFile(filePath string) (*Factory, error) {
cfg, err := config.LoadFromFile(filePath)
if err != nil {
return nil, fmt.Errorf("failed to load config: %w", err)
}
return NewFactory(cfg), nil
}
// GetEmailClient 获取邮件客户端(已初始化) // GetEmailClient 获取邮件客户端(已初始化)
// 返回已初始化的邮件客户端对象,可直接使用 // 返回已初始化的邮件客户端对象,可直接使用
func (f *Factory) GetEmailClient() (*email.Email, error) { func (f *Factory) GetEmailClient() (*email.Email, error) {
@@ -49,8 +64,63 @@ func (f *Factory) GetLogger() (*logger.Logger, error) {
return logger.NewLogger(f.cfg.Logger) return logger.NewLogger(f.cfg.Logger)
} }
// GetDatabase 获取数据库连接对象(已初始化)
// 返回已初始化的GORM数据库对象可直接使用
func (f *Factory) GetDatabase() (*gorm.DB, error) {
if f.cfg.Database == nil {
return nil, fmt.Errorf("database config is nil")
}
// 获取DSN
dsn, err := f.cfg.GetDatabaseDSN()
if err != nil {
return nil, fmt.Errorf("failed to get DSN: %w", err)
}
// 根据数据库类型创建连接
var db *gorm.DB
switch f.cfg.Database.Type {
case "mysql":
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
case "postgres":
db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
case "sqlite":
db, err = gorm.Open(sqlite.Open(dsn), &gorm.Config{})
default:
return nil, fmt.Errorf("unsupported database type: %s", f.cfg.Database.Type)
}
if err != nil {
return nil, fmt.Errorf("failed to connect to database: %w", err)
}
// 配置连接池
sqlDB, err := db.DB()
if err != nil {
return nil, fmt.Errorf("failed to get sql.DB: %w", err)
}
if f.cfg.Database.MaxOpenConns > 0 {
sqlDB.SetMaxOpenConns(f.cfg.Database.MaxOpenConns)
}
if f.cfg.Database.MaxIdleConns > 0 {
sqlDB.SetMaxIdleConns(f.cfg.Database.MaxIdleConns)
}
if f.cfg.Database.ConnMaxLifetime > 0 {
sqlDB.SetConnMaxLifetime(time.Duration(f.cfg.Database.ConnMaxLifetime) * time.Second)
}
return db, nil
}
// GetRedisConfig 获取Redis配置用于创建Redis客户端
// 返回Redis配置对象调用方可以使用此配置创建Redis客户端
// 注意Go标准库没有Redis客户端需要调用方使用第三方库如go-redis/redis创建
func (f *Factory) GetRedisConfig() *config.RedisConfig {
return f.cfg.Redis
}
// GetConfig 获取配置对象 // GetConfig 获取配置对象
func (f *Factory) GetConfig() *config.Config { func (f *Factory) GetConfig() *config.Config {
return f.cfg return f.cfg
} }

9
go.mod
View File

@@ -10,8 +10,15 @@ require (
require ( require (
github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.6.0 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/mattn/go-sqlite3 v1.14.22 // indirect
golang.org/x/text v0.20.0 // indirect golang.org/x/crypto v0.31.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/text v0.21.0 // indirect
gorm.io/driver/postgres v1.6.0 // indirect
) )

23
go.sum
View File

@@ -1,16 +1,39 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs= gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8= gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=