69 lines
2.1 KiB
Go
69 lines
2.1 KiB
Go
package cache
|
||
|
||
import (
|
||
"database/sql"
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
"sync"
|
||
"time"
|
||
|
||
_ "modernc.org/sqlite" // 纯 Go 驱动,驱动名是 "sqlite" 而非 "sqlite3"
|
||
)
|
||
|
||
var (
|
||
globalDB *sql.DB
|
||
once sync.Once // 确保 InitCache 只执行一次(单例初始化)
|
||
)
|
||
|
||
// InitCache 初始化 SQLite 数据库连接(全局唯一,兼容 CGO_ENABLED=0)
|
||
func InitCache() {
|
||
once.Do(func() {
|
||
// 1. 数据库文件路径(自定义为你的用户数据库路径)
|
||
dbPath := "./database/local/user.db"
|
||
|
||
// 2. 创建数据库目录(确保上级目录存在,不存在则自动创建)
|
||
if err := os.MkdirAll(filepath.Dir(dbPath), 0755); err != nil {
|
||
panic(fmt.Sprintf("创建数据库目录失败:%v", err))
|
||
}
|
||
|
||
// 3. 打开 SQLite 连接:驱动名必须是 "sqlite"(对应 modernc.org/sqlite)
|
||
db, err := sql.Open("sqlite", dbPath)
|
||
if err != nil {
|
||
panic(fmt.Sprintf("打开 SQLite 数据库失败:%v", err))
|
||
}
|
||
|
||
// 4. 验证连接有效性(必做,避免连接创建成功但不可用)
|
||
if err := db.Ping(); err != nil {
|
||
_ = db.Close() // 连接失败时释放资源
|
||
panic(fmt.Sprintf("验证 SQLite 连接失败:%v", err))
|
||
}
|
||
|
||
// 5. 连接池配置(适配 SQLite 单文件特性)
|
||
db.SetMaxOpenConns(1) // 最大打开连接数=1,避免文件锁冲突
|
||
db.SetMaxIdleConns(1) // 最大空闲连接数=1,与最大打开数一致
|
||
db.SetConnMaxLifetime(0) // 连接生命周期无限制
|
||
db.SetConnMaxIdleTime(30 * time.Minute) // 空闲连接30分钟超时释放
|
||
|
||
// 6. 赋值全局变量,初始化完成
|
||
globalDB = db
|
||
fmt.Printf("SQLite 数据库初始化成功,文件路径:%s\n", dbPath)
|
||
})
|
||
}
|
||
|
||
// GetCacheDB 获取全局唯一的 SQLite 连接(必须先调用 InitCache 初始化)
|
||
func GetCacheDB() *sql.DB {
|
||
if globalDB == nil {
|
||
panic("数据库未初始化,请先调用 cache.InitCache()")
|
||
}
|
||
return globalDB
|
||
}
|
||
|
||
// CloseCache 关闭数据库连接(程序退出时调用,释放资源)
|
||
func CloseCache() error {
|
||
if globalDB != nil {
|
||
return globalDB.Close()
|
||
}
|
||
return nil
|
||
}
|