初始版本,工具基础类

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

466
config/config.go Normal file
View File

@@ -0,0 +1,466 @@
package config
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"github.com/go-common/middleware"
)
// Config 应用配置
type Config struct {
Database *DatabaseConfig `json:"database"`
OSS *OSSConfig `json:"oss"`
Redis *RedisConfig `json:"redis"`
CORS *CORSConfig `json:"cors"`
MinIO *MinIOConfig `json:"minio"`
Email *EmailConfig `json:"email"`
SMS *SMSConfig `json:"sms"`
}
// DatabaseConfig 数据库配置
type DatabaseConfig struct {
// Type 数据库类型: mysql, postgres, sqlite
Type string `json:"type"`
// Host 数据库主机
Host string `json:"host"`
// Port 数据库端口
Port int `json:"port"`
// User 数据库用户名
User string `json:"user"`
// Password 数据库密码
Password string `json:"password"`
// Database 数据库名称
Database string `json:"database"`
// Charset 字符集MySQL使用
Charset string `json:"charset"`
// MaxOpenConns 最大打开连接数
MaxOpenConns int `json:"maxOpenConns"`
// MaxIdleConns 最大空闲连接数
MaxIdleConns int `json:"maxIdleConns"`
// ConnMaxLifetime 连接最大生存时间(秒)
ConnMaxLifetime int `json:"connMaxLifetime"`
// DSN 数据库连接字符串(如果设置了,会优先使用)
DSN string `json:"dsn"`
}
// OSSConfig OSS对象存储配置
type OSSConfig struct {
// Provider 提供商: aliyun, tencent, aws, qiniu
Provider string `json:"provider"`
// Endpoint 端点地址
Endpoint string `json:"endpoint"`
// AccessKeyID 访问密钥ID
AccessKeyID string `json:"accessKeyId"`
// AccessKeySecret 访问密钥
AccessKeySecret string `json:"accessKeySecret"`
// Bucket 存储桶名称
Bucket string `json:"bucket"`
// Region 区域
Region string `json:"region"`
// UseSSL 是否使用SSL
UseSSL bool `json:"useSSL"`
// Domain 自定义域名CDN域名
Domain string `json:"domain"`
}
// RedisConfig Redis配置
type RedisConfig struct {
// Host Redis主机
Host string `json:"host"`
// Port Redis端口
Port int `json:"port"`
// Password Redis密码
Password string `json:"password"`
// Database Redis数据库编号
Database int `json:"database"`
// MaxRetries 最大重试次数
MaxRetries int `json:"maxRetries"`
// PoolSize 连接池大小
PoolSize int `json:"poolSize"`
// MinIdleConns 最小空闲连接数
MinIdleConns int `json:"minIdleConns"`
// DialTimeout 连接超时时间(秒)
DialTimeout int `json:"dialTimeout"`
// ReadTimeout 读取超时时间(秒)
ReadTimeout int `json:"readTimeout"`
// WriteTimeout 写入超时时间(秒)
WriteTimeout int `json:"writeTimeout"`
// Addr Redis地址如果设置了会优先使用格式: host:port
Addr string `json:"addr"`
}
// CORSConfig CORS配置与middleware.CORSConfig兼容
type CORSConfig struct {
// AllowedOrigins 允许的源
AllowedOrigins []string `json:"allowedOrigins"`
// AllowedMethods 允许的HTTP方法
AllowedMethods []string `json:"allowedMethods"`
// AllowedHeaders 允许的请求头
AllowedHeaders []string `json:"allowedHeaders"`
// ExposedHeaders 暴露给客户端的响应头
ExposedHeaders []string `json:"exposedHeaders"`
// AllowCredentials 是否允许发送凭证
AllowCredentials bool `json:"allowCredentials"`
// MaxAge 预检请求的缓存时间(秒)
MaxAge int `json:"maxAge"`
}
// MinIOConfig MinIO配置
type MinIOConfig struct {
// Endpoint MinIO端点地址
Endpoint string `json:"endpoint"`
// AccessKeyID 访问密钥ID
AccessKeyID string `json:"accessKeyId"`
// SecretAccessKey 密钥
SecretAccessKey string `json:"secretAccessKey"`
// UseSSL 是否使用SSL
UseSSL bool `json:"useSSL"`
// Bucket 存储桶名称
Bucket string `json:"bucket"`
// Region 区域
Region string `json:"region"`
// Domain 自定义域名
Domain string `json:"domain"`
}
// EmailConfig 邮件配置
type EmailConfig struct {
// Host SMTP服务器地址
Host string `json:"host"`
// Port SMTP服务器端口
Port int `json:"port"`
// Username 发件人邮箱
Username string `json:"username"`
// Password 邮箱密码或授权码
Password string `json:"password"`
// From 发件人邮箱地址如果为空使用Username
From string `json:"from"`
// FromName 发件人名称
FromName string `json:"fromName"`
// UseTLS 是否使用TLS
UseTLS bool `json:"useTLS"`
// UseSSL 是否使用SSL
UseSSL bool `json:"useSSL"`
// Timeout 连接超时时间(秒)
Timeout int `json:"timeout"`
}
// SMSConfig 短信配置(阿里云短信)
type SMSConfig struct {
// AccessKeyID 阿里云AccessKey ID
AccessKeyID string `json:"accessKeyId"`
// AccessKeySecret 阿里云AccessKey Secret
AccessKeySecret string `json:"accessKeySecret"`
// Region 区域cn-hangzhou
Region string `json:"region"`
// SignName 短信签名
SignName string `json:"signName"`
// TemplateCode 短信模板代码
TemplateCode string `json:"templateCode"`
// Endpoint 服务端点(可选,默认使用区域端点)
Endpoint string `json:"endpoint"`
// Timeout 请求超时时间(秒)
Timeout int `json:"timeout"`
}
// LoadFromFile 从文件加载配置
// filePath: 配置文件路径(支持绝对路径和相对路径)
func LoadFromFile(filePath string) (*Config, error) {
// 转换为绝对路径
absPath, err := filepath.Abs(filePath)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path: %w", err)
}
// 读取文件
data, err := os.ReadFile(absPath)
if err != nil {
return nil, fmt.Errorf("failed to read config file: %w", err)
}
// 解析JSON
var config Config
if err := json.Unmarshal(data, &config); err != nil {
return nil, fmt.Errorf("failed to parse config file: %w", err)
}
// 设置默认值
config.setDefaults()
return &config, nil
}
// LoadFromBytes 从字节数组加载配置
func LoadFromBytes(data []byte) (*Config, error) {
var config Config
if err := json.Unmarshal(data, &config); err != nil {
return nil, fmt.Errorf("failed to parse config: %w", err)
}
// 设置默认值
config.setDefaults()
return &config, nil
}
// setDefaults 设置默认值
func (c *Config) setDefaults() {
// 数据库默认值
if c.Database != nil {
if c.Database.Charset == "" {
c.Database.Charset = "utf8mb4"
}
if c.Database.MaxOpenConns == 0 {
c.Database.MaxOpenConns = 100
}
if c.Database.MaxIdleConns == 0 {
c.Database.MaxIdleConns = 10
}
if c.Database.ConnMaxLifetime == 0 {
c.Database.ConnMaxLifetime = 3600
}
}
// Redis默认值
if c.Redis != nil {
if c.Redis.Port == 0 {
c.Redis.Port = 6379
}
if c.Redis.Database == 0 {
c.Redis.Database = 0
}
if c.Redis.MaxRetries == 0 {
c.Redis.MaxRetries = 3
}
if c.Redis.PoolSize == 0 {
c.Redis.PoolSize = 10
}
if c.Redis.MinIdleConns == 0 {
c.Redis.MinIdleConns = 5
}
if c.Redis.DialTimeout == 0 {
c.Redis.DialTimeout = 5
}
if c.Redis.ReadTimeout == 0 {
c.Redis.ReadTimeout = 3
}
if c.Redis.WriteTimeout == 0 {
c.Redis.WriteTimeout = 3
}
}
// CORS默认值
if c.CORS != nil {
if len(c.CORS.AllowedOrigins) == 0 {
c.CORS.AllowedOrigins = []string{"*"}
}
if len(c.CORS.AllowedMethods) == 0 {
c.CORS.AllowedMethods = []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"}
}
if len(c.CORS.AllowedHeaders) == 0 {
c.CORS.AllowedHeaders = []string{"Content-Type", "Authorization", "X-Requested-With", "X-Timezone"}
}
if c.CORS.MaxAge == 0 {
c.CORS.MaxAge = 86400
}
}
// 邮件默认值
if c.Email != nil {
if c.Email.Port == 0 {
c.Email.Port = 587 // 默认使用587端口TLS
}
if c.Email.From == "" {
c.Email.From = c.Email.Username
}
if c.Email.Timeout == 0 {
c.Email.Timeout = 30
}
}
// 短信默认值
if c.SMS != nil {
if c.SMS.Region == "" {
c.SMS.Region = "cn-hangzhou"
}
if c.SMS.Timeout == 0 {
c.SMS.Timeout = 10
}
}
}
// GetDatabase 获取数据库配置
func (c *Config) GetDatabase() *DatabaseConfig {
return c.Database
}
// GetOSS 获取OSS配置
func (c *Config) GetOSS() *OSSConfig {
return c.OSS
}
// GetRedis 获取Redis配置
func (c *Config) GetRedis() *RedisConfig {
return c.Redis
}
// GetCORS 获取CORS配置并转换为middleware.CORSConfig
func (c *Config) GetCORS() *middleware.CORSConfig {
if c.CORS == nil {
return middleware.DefaultCORSConfig()
}
return &middleware.CORSConfig{
AllowedOrigins: c.CORS.AllowedOrigins,
AllowedMethods: c.CORS.AllowedMethods,
AllowedHeaders: c.CORS.AllowedHeaders,
ExposedHeaders: c.CORS.ExposedHeaders,
AllowCredentials: c.CORS.AllowCredentials,
MaxAge: c.CORS.MaxAge,
}
}
// GetMinIO 获取MinIO配置
func (c *Config) GetMinIO() *MinIOConfig {
return c.MinIO
}
// GetEmail 获取邮件配置
func (c *Config) GetEmail() *EmailConfig {
return c.Email
}
// GetSMS 获取短信配置
func (c *Config) GetSMS() *SMSConfig {
return c.SMS
}
// GetDatabaseDSN 获取数据库连接字符串
func (c *Config) GetDatabaseDSN() (string, error) {
if c.Database == nil {
return "", fmt.Errorf("database config is nil")
}
// 如果已经设置了DSN直接返回
if c.Database.DSN != "" {
return c.Database.DSN, nil
}
// 根据数据库类型生成DSN
switch c.Database.Type {
case "mysql":
return c.buildMySQLDSN(), nil
case "postgres":
return c.buildPostgresDSN(), nil
case "sqlite":
return c.Database.Database, nil
default:
return "", fmt.Errorf("unsupported database type: %s", c.Database.Type)
}
}
// buildMySQLDSN 构建MySQL连接字符串
// 注意数据库时间统一使用UTC时间不设置时区
func (c *Config) buildMySQLDSN() string {
db := c.Database
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", db.User, db.Password, db.Host, db.Port, db.Database)
params := []string{}
if db.Charset != "" {
params = append(params, "charset="+db.Charset)
}
params = append(params, "parseTime=True")
params = append(params, "loc=UTC") // 统一使用UTC时区
if len(params) > 0 {
dsn += "?" + params[0]
for i := 1; i < len(params); i++ {
dsn += "&" + params[i]
}
}
return dsn
}
// buildPostgresDSN 构建PostgreSQL连接字符串
// 注意数据库时间统一使用UTC时间不设置时区
func (c *Config) buildPostgresDSN() string {
db := c.Database
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s",
db.Host, db.Port, db.User, db.Password, db.Database)
// 统一使用UTC时区
dsn += " timezone=UTC"
dsn += " sslmode=disable"
return dsn
}
// GetRedisAddr 获取Redis地址
func (c *Config) GetRedisAddr() string {
if c.Redis == nil {
return ""
}
// 如果已经设置了Addr直接返回
if c.Redis.Addr != "" {
return c.Redis.Addr
}
// 构建地址
return fmt.Sprintf("%s:%d", c.Redis.Host, c.Redis.Port)
}

74
config/example.json Normal file
View File

@@ -0,0 +1,74 @@
{
"database": {
"type": "mysql",
"host": "localhost",
"port": 3306,
"user": "root",
"password": "password",
"database": "testdb",
"charset": "utf8mb4",
"maxOpenConns": 100,
"maxIdleConns": 10,
"connMaxLifetime": 3600
},
"oss": {
"provider": "aliyun",
"endpoint": "oss-cn-hangzhou.aliyuncs.com",
"accessKeyId": "your-access-key-id",
"accessKeySecret": "your-access-key-secret",
"bucket": "your-bucket-name",
"region": "cn-hangzhou",
"useSSL": true,
"domain": "https://cdn.example.com"
},
"redis": {
"host": "localhost",
"port": 6379,
"password": "",
"database": 0,
"maxRetries": 3,
"poolSize": 10,
"minIdleConns": 5,
"dialTimeout": 5,
"readTimeout": 3,
"writeTimeout": 3
},
"cors": {
"allowedOrigins": ["*"],
"allowedMethods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
"allowedHeaders": ["Content-Type", "Authorization", "X-Requested-With", "X-Timezone"],
"exposedHeaders": [],
"allowCredentials": false,
"maxAge": 86400
},
"minio": {
"endpoint": "localhost:9000",
"accessKeyId": "minioadmin",
"secretAccessKey": "minioadmin",
"useSSL": false,
"bucket": "test-bucket",
"region": "us-east-1",
"domain": "http://localhost:9000"
},
"email": {
"host": "smtp.example.com",
"port": 587,
"username": "your-email@example.com",
"password": "your-email-password",
"from": "your-email@example.com",
"fromName": "Your App Name",
"useTLS": true,
"useSSL": false,
"timeout": 30
},
"sms": {
"accessKeyId": "your-aliyun-access-key-id",
"accessKeySecret": "your-aliyun-access-key-secret",
"region": "cn-hangzhou",
"signName": "Your Sign Name",
"templateCode": "SMS_123456789",
"endpoint": "",
"timeout": 10
}
}