初始版本,工具基础类

This commit is contained in:
2025-11-30 13:02:34 +08:00
commit ea4e2e305d
37 changed files with 7480 additions and 0 deletions

124
examples/config_example.go Normal file
View File

@@ -0,0 +1,124 @@
package main
import (
"fmt"
"log"
"github.com/go-common/config"
"github.com/go-common/middleware"
// "gorm.io/driver/mysql"
// "gorm.io/gorm"
)
func main() {
// 加载配置文件
cfg, err := config.LoadFromFile("./config/example.json")
if err != nil {
log.Fatal("Failed to load config:", err)
}
// 1. 使用数据库配置
fmt.Println("=== Database Config ===")
dbConfig := cfg.GetDatabase()
if dbConfig != nil {
fmt.Printf("Type: %s\n", dbConfig.Type)
fmt.Printf("Host: %s:%d\n", dbConfig.Host, dbConfig.Port)
fmt.Printf("Database: %s\n", dbConfig.Database)
fmt.Printf("User: %s\n", dbConfig.User)
}
// 获取数据库连接字符串
dsn, err := cfg.GetDatabaseDSN()
if err != nil {
log.Printf("Failed to get DSN: %v", err)
} else {
fmt.Printf("DSN: %s\n", dsn)
// 实际使用时可以这样连接数据库
// db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// if err != nil {
// log.Fatal(err)
// }
}
// 2. 使用OSS配置
fmt.Println("\n=== OSS Config ===")
ossConfig := cfg.GetOSS()
if ossConfig != nil {
fmt.Printf("Provider: %s\n", ossConfig.Provider)
fmt.Printf("Endpoint: %s\n", ossConfig.Endpoint)
fmt.Printf("Bucket: %s\n", ossConfig.Bucket)
fmt.Printf("Region: %s\n", ossConfig.Region)
}
// 3. 使用Redis配置
fmt.Println("\n=== Redis Config ===")
redisConfig := cfg.GetRedis()
if redisConfig != nil {
fmt.Printf("Host: %s\n", redisConfig.Host)
fmt.Printf("Port: %d\n", redisConfig.Port)
fmt.Printf("Database: %d\n", redisConfig.Database)
}
// 获取Redis地址
redisAddr := cfg.GetRedisAddr()
fmt.Printf("Redis Address: %s\n", redisAddr)
// 4. 使用CORS配置
fmt.Println("\n=== CORS Config ===")
corsConfig := cfg.GetCORS()
if corsConfig != nil {
fmt.Printf("Allowed Origins: %v\n", corsConfig.AllowedOrigins)
fmt.Printf("Allowed Methods: %v\n", corsConfig.AllowedMethods)
fmt.Printf("Max Age: %d\n", corsConfig.MaxAge)
}
// 使用CORS配置创建中间件
chain := middleware.NewChain(
middleware.CORS(corsConfig),
)
fmt.Printf("CORS middleware created: %v\n", chain != nil)
// 5. 使用MinIO配置
fmt.Println("\n=== MinIO Config ===")
minioConfig := cfg.GetMinIO()
if minioConfig != nil {
fmt.Printf("Endpoint: %s\n", minioConfig.Endpoint)
fmt.Printf("Bucket: %s\n", minioConfig.Bucket)
fmt.Printf("UseSSL: %v\n", minioConfig.UseSSL)
}
// 6. 使用邮件配置
fmt.Println("\n=== Email Config ===")
emailConfig := cfg.GetEmail()
if emailConfig != nil {
fmt.Printf("Host: %s:%d\n", emailConfig.Host, emailConfig.Port)
fmt.Printf("From: %s <%s>\n", emailConfig.FromName, emailConfig.From)
fmt.Printf("UseTLS: %v\n", emailConfig.UseTLS)
}
// 7. 使用短信配置
fmt.Println("\n=== SMS Config ===")
smsConfig := cfg.GetSMS()
if smsConfig != nil {
fmt.Printf("Region: %s\n", smsConfig.Region)
fmt.Printf("Sign Name: %s\n", smsConfig.SignName)
fmt.Printf("Template Code: %s\n", smsConfig.TemplateCode)
}
// 示例:实际使用配置连接数据库
fmt.Println("\n=== Example: Connect to Database ===")
if dbConfig != nil && dbConfig.Type == "mysql" {
// 注意:这里只是示例,实际使用时需要确保数据库服务正在运行
// db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// if err != nil {
// log.Printf("Failed to connect to database: %v", err)
// } else {
// fmt.Println("Database connected successfully")
// sqlDB, _ := db.DB()
// sqlDB.SetMaxOpenConns(dbConfig.MaxOpenConns)
// sqlDB.SetMaxIdleConns(dbConfig.MaxIdleConns)
// sqlDB.SetConnMaxLifetime(time.Duration(dbConfig.ConnMaxLifetime) * time.Second)
// }
fmt.Println("Database connection example (commented out)")
}
}

View File

@@ -0,0 +1,56 @@
package main
import (
"fmt"
"log"
"time"
"github.com/go-common/datetime"
)
func main() {
// 设置默认时区
err := datetime.SetDefaultTimeZone(datetime.AsiaShanghai)
if err != nil {
log.Fatal(err)
}
// 获取当前时间
now := datetime.Now()
fmt.Printf("Current time: %s\n", datetime.FormatDateTime(now))
// 解析时间字符串
t, err := datetime.ParseDateTime("2024-01-01 12:00:00")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Parsed time: %s\n", datetime.FormatDateTime(t))
// 时区转换
t2, err := datetime.ToTimezone(t, datetime.AmericaNewYork)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Time in New York: %s\n", datetime.FormatDateTime(t2))
// Unix时间戳
unix := datetime.ToUnix(now)
fmt.Printf("Unix timestamp: %d\n", unix)
t3 := datetime.FromUnix(unix)
fmt.Printf("From Unix: %s\n", datetime.FormatDateTime(t3))
// 时间计算
tomorrow := datetime.AddDays(now, 1)
fmt.Printf("Tomorrow: %s\n", datetime.FormatDate(tomorrow))
// 时间范围
startOfDay := datetime.StartOfDay(now)
endOfDay := datetime.EndOfDay(now)
fmt.Printf("Start of day: %s\n", datetime.FormatDateTime(startOfDay))
fmt.Printf("End of day: %s\n", datetime.FormatDateTime(endOfDay))
// 时间差
diff := datetime.DiffDays(now, tomorrow)
fmt.Printf("Days difference: %d\n", diff)
}

View File

@@ -0,0 +1,74 @@
package main
import (
"fmt"
"log"
"time"
"github.com/go-common/datetime"
)
func main() {
// 示例1将当前时间转换为UTC
fmt.Println("=== Example 1: Convert Current Time to UTC ===")
now := time.Now()
utcTime := datetime.ToUTC(now)
fmt.Printf("Local time: %s\n", datetime.FormatDateTime(now))
fmt.Printf("UTC time: %s\n", datetime.FormatDateTime(utcTime))
// 示例2从指定时区转换为UTC
fmt.Println("\n=== Example 2: Convert from Specific Timezone to UTC ===")
// 解析上海时区的时间
shanghaiTime, err := datetime.ParseDateTime("2024-01-01 12:00:00", datetime.AsiaShanghai)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Shanghai time: %s\n", datetime.FormatDateTime(shanghaiTime, datetime.AsiaShanghai))
// 转换为UTC
utcTime2, err := datetime.ToUTCFromTimezone(shanghaiTime, datetime.AsiaShanghai)
if err != nil {
log.Fatal(err)
}
fmt.Printf("UTC time: %s\n", datetime.FormatDateTime(utcTime2, datetime.UTC))
// 示例3解析时间字符串并直接转换为UTC
fmt.Println("\n=== Example 3: Parse and Convert to UTC ===")
utcTime3, err := datetime.ParseDateTimeToUTC("2024-01-01 12:00:00", datetime.AsiaShanghai)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Parsed from Shanghai timezone, UTC: %s\n", datetime.FormatDateTime(utcTime3, datetime.UTC))
// 示例4解析日期并转换为UTC
fmt.Println("\n=== Example 4: Parse Date and Convert to UTC ===")
utcTime4, err := datetime.ParseDateToUTC("2024-01-01", datetime.AsiaShanghai)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Date parsed from Shanghai timezone, UTC: %s\n", datetime.FormatDateTime(utcTime4, datetime.UTC))
// 示例5数据库存储场景
fmt.Println("\n=== Example 5: Database Storage Scenario ===")
// 从请求中获取时间(假设是上海时区)
requestTimeStr := "2024-01-01 12:00:00"
requestTimezone := datetime.AsiaShanghai
// 转换为UTC时间用于数据库存储
dbTime, err := datetime.ParseDateTimeToUTC(requestTimeStr, requestTimezone)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Request time (Shanghai): %s\n", requestTimeStr)
fmt.Printf("Database time (UTC): %s\n", datetime.FormatDateTime(dbTime, datetime.UTC))
// 从数据库读取UTC时间转换为用户时区显示
userTimezone := datetime.AsiaShanghai
displayTime, err := datetime.ToTimezone(dbTime, userTimezone)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Display time (Shanghai): %s\n", datetime.FormatDateTime(displayTime, userTimezone))
}

121
examples/email_example.go Normal file
View File

@@ -0,0 +1,121 @@
package main
import (
"fmt"
"log"
"github.com/go-common/config"
"github.com/go-common/email"
)
func main() {
// 加载配置
cfg, err := config.LoadFromFile("./config/example.json")
if err != nil {
log.Fatal("Failed to load config:", err)
}
// 创建邮件发送器
emailConfig := cfg.GetEmail()
if emailConfig == nil {
log.Fatal("Email config is nil")
}
mailer, err := email.NewEmail(emailConfig)
if err != nil {
log.Fatal("Failed to create email client:", err)
}
// 示例1发送原始邮件内容推荐最灵活
fmt.Println("=== Example 1: Send Raw Email Content ===")
// 外部构建完整的邮件内容MIME格式
emailBody := []byte(`From: ` + emailConfig.From + `
To: recipient@example.com
Subject: 原始邮件测试
Content-Type: text/html; charset=UTF-8
<html>
<body>
<h1>这是原始邮件内容</h1>
<p>由外部完全控制邮件格式和内容</p>
</body>
</html>
`)
err = mailer.SendRaw(
[]string{"recipient@example.com"},
emailBody,
)
if err != nil {
log.Printf("Failed to send raw email: %v", err)
} else {
fmt.Println("Raw email sent successfully")
}
// 示例2发送简单邮件便捷方法
fmt.Println("\n=== Example 2: Send Simple Email ===")
err = mailer.SendSimple(
[]string{"recipient@example.com"},
"测试邮件",
"这是一封测试邮件使用Go标准库发送。",
)
if err != nil {
log.Printf("Failed to send email: %v", err)
} else {
fmt.Println("Email sent successfully")
}
// 示例3发送HTML邮件
fmt.Println("\n=== Example 3: Send HTML Email ===")
htmlBody := `
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>欢迎使用邮件服务</h1>
<p>这是一封HTML格式的邮件。</p>
<p>支持<strong>富文本</strong>格式。</p>
</body>
</html>
`
err = mailer.SendHTML(
[]string{"recipient@example.com"},
"HTML邮件测试",
htmlBody,
)
if err != nil {
log.Printf("Failed to send HTML email: %v", err)
} else {
fmt.Println("HTML email sent successfully")
}
// 示例4发送完整邮件包含抄送、密送
fmt.Println("\n=== Example 4: Send Full Email ===")
msg := &email.Message{
To: []string{"to@example.com"},
Cc: []string{"cc@example.com"},
Bcc: []string{"bcc@example.com"},
Subject: "完整邮件示例",
Body: "这是纯文本正文",
HTMLBody: `
<html>
<body>
<h1>这是HTML正文</h1>
<p>支持同时发送纯文本和HTML版本。</p>
</body>
</html>
`,
}
err = mailer.Send(msg)
if err != nil {
log.Printf("Failed to send full email: %v", err)
} else {
fmt.Println("Full email sent successfully")
}
fmt.Println("\nNote: Make sure your email configuration is correct and SMTP service is enabled.")
}

101
examples/http_example.go Normal file
View File

@@ -0,0 +1,101 @@
package main
import (
"log"
"net/http"
"github.com/go-common/http"
)
// 用户结构
type User struct {
ID int64 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
// 获取用户列表
func GetUserList(w http.ResponseWriter, r *http.Request) {
// 获取分页参数
page, pageSize := http.GetPaginationParams(r)
// 获取查询参数
keyword := http.GetQuery(r, "keyword", "")
// 模拟查询数据
users := []User{
{ID: 1, Name: "User1", Email: "user1@example.com"},
{ID: 2, Name: "User2", Email: "user2@example.com"},
}
total := int64(100)
// 返回分页响应
http.SuccessPage(w, users, total, page, pageSize)
}
// 创建用户
func CreateUser(w http.ResponseWriter, r *http.Request) {
// 解析请求体
var req struct {
Name string `json:"name"`
Email string `json:"email"`
}
if err := http.ParseJSON(r, &req); err != nil {
http.BadRequest(w, "请求参数解析失败")
return
}
// 参数验证
if req.Name == "" {
http.Error(w, 1001, "用户名不能为空")
return
}
// 模拟创建用户
user := User{
ID: 1,
Name: req.Name,
Email: req.Email,
}
// 返回成功响应
http.SuccessWithMessage(w, "创建成功", user)
}
// 获取用户详情
func GetUser(w http.ResponseWriter, r *http.Request) {
// 获取查询参数
id := http.GetQueryInt64(r, "id", 0)
if id == 0 {
http.BadRequest(w, "用户ID不能为空")
return
}
// 模拟查询用户
if id == 1 {
user := User{ID: 1, Name: "User1", Email: "user1@example.com"}
http.Success(w, user)
} else {
http.Error(w, 1002, "用户不存在")
}
}
func main() {
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
GetUserList(w, r)
case http.MethodPost:
CreateUser(w, r)
default:
http.NotFound(w, "方法不支持")
}
})
http.HandleFunc("/user", GetUser)
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}

View File

@@ -0,0 +1,64 @@
package main
import (
"log"
"net/http"
"github.com/go-common/datetime"
"github.com/go-common/http"
"github.com/go-common/middleware"
)
// 示例使用CORS和时区中间件
func main() {
// 配置CORS
corsConfig := &middleware.CORSConfig{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{
"Content-Type",
"Authorization",
"X-Requested-With",
"X-Timezone",
},
AllowCredentials: false,
MaxAge: 3600,
}
// 创建中间件链
chain := middleware.NewChain(
middleware.CORS(corsConfig),
middleware.Timezone,
)
// 定义处理器
handler := chain.ThenFunc(apiHandler)
// 注册路由
http.Handle("/api", handler)
log.Println("Server started on :8080")
log.Println("Try: curl -H 'X-Timezone: America/New_York' http://localhost:8080/api")
log.Fatal(http.ListenAndServe(":8080", nil))
}
// apiHandler 处理API请求
func apiHandler(w http.ResponseWriter, r *http.Request) {
// 从context获取时区
timezone := http.GetTimezone(r)
// 使用时区进行时间处理
now := datetime.Now(timezone)
startOfDay := datetime.StartOfDay(now, timezone)
endOfDay := datetime.EndOfDay(now, timezone)
// 返回响应
http.Success(w, map[string]interface{}{
"message": "Hello from API",
"timezone": timezone,
"currentTime": datetime.FormatDateTime(now),
"startOfDay": datetime.FormatDateTime(startOfDay),
"endOfDay": datetime.FormatDateTime(endOfDay),
})
}

View File

@@ -0,0 +1,58 @@
package main
import (
"fmt"
"log"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"github.com/go-common/migration"
)
func main() {
// 初始化数据库连接
dsn := "user:password@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
// 创建迁移器
migrator := migration.NewMigrator(db)
// 添加迁移
migrator.AddMigration(migration.Migration{
Version: "20240101000001",
Description: "create_users_table",
Up: func(db *gorm.DB) error {
return db.Exec(`
CREATE TABLE IF NOT EXISTS users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`).Error
},
Down: func(db *gorm.DB) error {
return db.Exec("DROP TABLE IF EXISTS users").Error
},
})
// 执行迁移
if err := migrator.Up(); err != nil {
log.Fatal(err)
}
// 查看迁移状态
status, err := migrator.Status()
if err != nil {
log.Fatal(err)
}
for _, s := range status {
fmt.Printf("Version: %s, Description: %s, Applied: %v\n",
s.Version, s.Description, s.Applied)
}
}

102
examples/sms_example.go Normal file
View File

@@ -0,0 +1,102 @@
package main
import (
"fmt"
"log"
"github.com/go-common/config"
"github.com/go-common/sms"
)
func main() {
// 加载配置
cfg, err := config.LoadFromFile("./config/example.json")
if err != nil {
log.Fatal("Failed to load config:", err)
}
// 创建短信发送器
smsConfig := cfg.GetSMS()
if smsConfig == nil {
log.Fatal("SMS config is nil")
}
smsClient, err := sms.NewSMS(smsConfig)
if err != nil {
log.Fatal("Failed to create SMS client:", err)
}
// 示例1发送原始请求推荐最灵活
fmt.Println("=== Example 1: Send Raw SMS Request ===")
// 外部构建完整的请求参数
params := map[string]string{
"PhoneNumbers": "13800138000",
"SignName": smsConfig.SignName,
"TemplateCode": smsConfig.TemplateCode,
"TemplateParam": `{"code":"123456","expire":"5"}`,
}
resp, err := smsClient.SendRaw(params)
if err != nil {
log.Printf("Failed to send raw SMS: %v", err)
} else {
fmt.Printf("Raw SMS sent successfully, RequestID: %s\n", resp.RequestID)
}
// 示例2发送简单短信使用配置中的模板代码
fmt.Println("\n=== Example 2: Send Simple SMS ===")
templateParam := map[string]string{
"code": "123456",
"expire": "5",
}
resp2, err := smsClient.SendSimple(
[]string{"13800138000"},
templateParam,
)
if err != nil {
log.Printf("Failed to send SMS: %v", err)
} else {
fmt.Printf("SMS sent successfully, RequestID: %s\n", resp2.RequestID)
}
// 示例3使用指定模板发送短信
fmt.Println("\n=== Example 3: Send SMS with Template ===")
templateParam3 := map[string]string{
"code": "654321",
"expire": "10",
}
resp3, err := smsClient.SendWithTemplate(
[]string{"13800138000"},
"SMS_123456789", // 使用指定的模板代码
templateParam3,
)
if err != nil {
log.Printf("Failed to send SMS: %v", err)
} else {
fmt.Printf("SMS sent successfully, RequestID: %s\n", resp3.RequestID)
}
// 示例4使用JSON字符串作为模板参数
fmt.Println("\n=== Example 4: Send SMS with JSON String Template Param ===")
req := &sms.SendRequest{
PhoneNumbers: []string{"13800138000"},
TemplateCode: smsConfig.TemplateCode,
TemplateParam: `{"code":"888888","expire":"15"}`, // 直接使用JSON字符串
}
resp4, err := smsClient.Send(req)
if err != nil {
log.Printf("Failed to send SMS: %v", err)
} else {
fmt.Printf("SMS sent successfully, RequestID: %s\n", resp4.RequestID)
}
fmt.Println("\nNote: Make sure your Aliyun SMS service is configured correctly:")
fmt.Println("1. AccessKey ID and Secret are valid")
fmt.Println("2. Sign name is approved")
fmt.Println("3. Template code is approved")
fmt.Println("4. Template parameters match the template definition")
}

View File

@@ -0,0 +1,71 @@
package main
import (
"log"
"net/http"
"github.com/go-common/config"
"github.com/go-common/middleware"
"github.com/go-common/storage"
)
func main() {
// 加载配置
cfg, err := config.LoadFromFile("./config/example.json")
if err != nil {
log.Fatal("Failed to load config:", err)
}
// 创建存储实例使用OSS
// 注意需要先实现OSS SDK集成
ossStorage, err := storage.NewStorage(storage.StorageTypeOSS, cfg)
if err != nil {
log.Printf("Failed to create OSS storage: %v", err)
log.Println("Note: OSS SDK integration is required")
// 继续演示其他功能
} else {
// 创建上传处理器
uploadHandler := storage.NewUploadHandler(storage.UploadHandlerConfig{
Storage: ossStorage,
MaxFileSize: 10 * 1024 * 1024, // 10MB
AllowedExts: []string{".jpg", ".jpeg", ".png", ".gif", ".pdf"},
ObjectPrefix: "uploads/",
})
// 创建代理查看处理器
proxyHandler := storage.NewProxyHandler(ossStorage)
// 创建中间件链
chain := middleware.NewChain(
middleware.CORS(cfg.GetCORS()),
middleware.Timezone,
)
// 注册路由
mux := http.NewServeMux()
mux.Handle("/upload", chain.Then(uploadHandler))
mux.Handle("/file", chain.Then(proxyHandler))
log.Println("Storage server started on :8080")
log.Println("Upload: POST /upload")
log.Println("View: GET /file?key=images/test.jpg")
log.Fatal(http.ListenAndServe(":8080", mux))
}
// 演示MinIO存储
minioStorage, err := storage.NewStorage(storage.StorageTypeMinIO, cfg)
if err != nil {
log.Printf("Failed to create MinIO storage: %v", err)
log.Println("Note: MinIO SDK integration is required")
} else {
log.Printf("MinIO storage created: %v", minioStorage != nil)
}
// 演示对象键生成
objectKey1 := storage.GenerateObjectKey("images/", "test.jpg")
log.Printf("Object key 1: %s", objectKey1)
objectKey2 := storage.GenerateObjectKeyWithDate("images", "test.jpg")
log.Printf("Object key 2: %s", objectKey2)
}