package services import ( // "context" "fmt" "net/url" "sync" "time" "github.com/jmoiron/sqlx" _ "github.com/go-sql-driver/mysql" // MySQL驱动(匿名导入) ) // Config 数据库连接配置 type Config struct { User string // 用户名 Password string // 密码 Host string // 主机地址(如localhost) Port int // 端口(默认3306) DBName string // 数据库名 Charset string // 字符集(默认utf8mb4) ParseTime bool // 是否解析时间(必须为true,否则time.Time无法解析) Loc string // 时区(默认Local或Asia/Shanghai) MaxOpenConns int // 最大打开连接数(默认100) MaxIdleConns int // 最大空闲连接数(默认20) ConnMaxLifetime time.Duration // 连接最大存活时间(默认1小时) ConnMaxIdleTime time.Duration // 连接最大空闲时间(默认30分钟) } // DefaultConfig 返回默认配置(可直接修改字段覆盖) func DefaultConfig(user string, password string, host string, port int, dbname string) *Config { escapedPassword := url.QueryEscape(password) return &Config{ User: user, Password: escapedPassword, // 替换为你的MySQL密码 Host: host, DBName: dbname, Port: port, Charset: "utf8mb4", ParseTime: true, Loc: "Local", MaxOpenConns: 20, MaxIdleConns: 5, ConnMaxLifetime: 1 * time.Hour, ConnMaxIdleTime: 30 * time.Minute, } } // DSN 生成MySQL连接字符串(Data Source Name) func (c *Config) DSN() string { return fmt.Sprintf( "%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=%t&loc=%s", c.User, c.Password, c.Host, c.Port, c.DBName, c.Charset, c.ParseTime, c.Loc, ) } // NewPool 初始化MySQL连接池 // 返回*sql.DB(Go内置连接池),使用后需调用Close()释放 func NewPool(config *Config) *sqlx.DB { // 打开数据库连接(不会立即建立连接,只是初始化连接池) db, err := sqlx.Open("mysql", config.DSN()) if err != nil { build_time_str := time.Now().Format(time.DateTime) fmt.Printf("%s open db failed:======> %v\n", build_time_str, err) return nil } // 设置连接池参数 db.SetMaxOpenConns(config.MaxOpenConns) // 控制并发连接数 db.SetMaxIdleConns(config.MaxIdleConns) // 保持空闲连接,减少创建开销 db.SetConnMaxLifetime(config.ConnMaxLifetime) // 避免连接被MySQL主动断开 db.SetConnMaxIdleTime(config.ConnMaxIdleTime) // 清理长时间空闲的连接 // 测试连接有效性 if err := db.Ping(); err != nil { db.Close() // 测试失败时关闭连接池 build_time_str := time.Now().Format(time.DateTime) fmt.Printf("%s ping db failed:======> %v\n", build_time_str, err) return nil } build_time := time.Now() build_time_str := build_time.Format(time.DateTime) fmt.Printf("%s mysql数据库连接池初始化成功\n", build_time_str) warmUpConnectionPoolConcurrently(db, 5) return db } func warmUpConnectionPoolConcurrently(db *sqlx.DB, warmUpCount int) error { var wg sync.WaitGroup errors := make(chan error, warmUpCount) for i := 0; i < warmUpCount; i++ { wg.Add(1) go func() { defer wg.Done() var dummy int err := db.QueryRow("SELECT 1").Scan(&dummy) if err != nil { errors <- fmt.Errorf("连接预热失败: %v", err) } }() } wg.Wait() close(errors) // 检查是否有错误 for err := range errors { return err } build_time := time.Now() build_time_str := build_time.Format(time.DateTime) fmt.Printf("%s 并发预热 %d 个连接成功\n", build_time_str, warmUpCount) return nil }