1 介绍

1.1 定义

01.技术概述
    a.基本概念
        Go SQLite是Go语言中操作SQLite数据库的技术方案,通过database/sql标准接口结合SQLite驱动实现对嵌入式数据库的访问。SQLite是一个轻量级的嵌入式关系型数据库,无需独立服务器进程,数据存储在单个文件中,非常适合桌面应用、移动应用和嵌入式系统使用。
    b.核心驱动
        a.go-sqlite3驱动
            a.功能说明
                go-sqlite3是Go语言中最成熟的SQLite驱动,基于CGO实现与SQLite C库的绑定。该驱动完整实现了database/sql接口,支持SQLite的所有特性,包括事务、预编译语句、自定义函数等。由于依赖CGO,编译时需要C编译器环境。
            b.代码示例
                ---
                // go-sqlite3基础连接示例
                package main

                import (
                    "database/sql"
                    "fmt"
                    "log"

                    // 导入go-sqlite3驱动,使用下划线表示仅执行init函数注册驱动
                    _ "github.com/mattn/go-sqlite3"
                )

                func main() {
                    // 打开或创建数据库文件
                    // 如果文件不存在,SQLite会自动创建
                    db, err := sql.Open("sqlite3", "./test.db")
                    if err != nil {
                        log.Fatal("打开数据库失败:", err)
                    }
                    defer db.Close()

                    // 验证数据库连接是否有效
                    if err := db.Ping(); err != nil {
                        log.Fatal("数据库连接验证失败:", err)
                    }

                    fmt.Println("成功连接到SQLite数据库")
                }
                ---
        b.modernc-sqlite驱动
            a.功能说明
                modernc.org/sqlite是纯Go实现的SQLite驱动,无需CGO依赖。该驱动将SQLite的C代码通过c2go工具转换为Go代码,实现了跨平台编译的便利性。虽然性能略低于CGO版本,但在无法使用CGO的环境中是最佳选择。
            b.代码示例
                ---
                // modernc-sqlite纯Go驱动连接示例
                package main

                import (
                    "database/sql"
                    "fmt"
                    "log"

                    // 导入纯Go实现的SQLite驱动
                    _ "modernc.org/sqlite"
                )

                func main() {
                    // 使用sqlite驱动名称(注意与go-sqlite3的sqlite3不同)
                    db, err := sql.Open("sqlite", "./app.db")
                    if err != nil {
                        log.Fatal("打开数据库失败:", err)
                    }
                    defer db.Close()

                    // 设置连接参数,纯Go驱动支持的参数略有不同
                    db.SetMaxOpenConns(1) // SQLite单文件建议单连接

                    if err := db.Ping(); err != nil {
                        log.Fatal("连接验证失败:", err)
                    }

                    fmt.Println("纯Go SQLite驱动连接成功")
                }
                ---

02.标准接口
    a.database/sql包
        a.设计理念
            database/sql是Go标准库提供的通用数据库接口,定义了与关系型数据库交互的标准API。该包采用接口抽象设计,通过驱动注册机制实现对不同数据库的统一访问,开发者无需关心底层数据库差异即可编写可移植的数据库代码。
        b.核心类型
            ---
            // database/sql核心类型说明
            package main

            import (
                "context"
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                // sql.DB: 数据库连接池,线程安全,应全局复用
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 创建测试表
                _, err = db.Exec(`CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)`)
                if err != nil {
                    log.Fatal(err)
                }

                // sql.Tx: 事务对象,用于执行事务操作
                tx, err := db.Begin()
                if err != nil {
                    log.Fatal(err)
                }

                // sql.Stmt: 预编译语句,可复用提高性能
                stmt, err := tx.Prepare("INSERT INTO users (name) VALUES (?)")
                if err != nil {
                    tx.Rollback()
                    log.Fatal(err)
                }
                defer stmt.Close()

                // 执行预编译语句
                _, err = stmt.Exec("Alice")
                if err != nil {
                    tx.Rollback()
                    log.Fatal(err)
                }

                tx.Commit()

                // sql.Rows: 查询结果集,需要遍历读取
                ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
                defer cancel()

                rows, err := db.QueryContext(ctx, "SELECT id, name FROM users")
                if err != nil {
                    log.Fatal(err)
                }
                defer rows.Close()

                for rows.Next() {
                    var id int
                    var name string
                    if err := rows.Scan(&id, &name); err != nil {
                        log.Fatal(err)
                    }
                    fmt.Printf("用户: ID=%d, Name=%s\n", id, name)
                }

                // sql.Row: 单行查询结果
                var count int
                err = db.QueryRow("SELECT COUNT(*) FROM users").Scan(&count)
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Printf("用户总数: %d\n", count)
            }
            ---
    b.驱动注册机制
        a.功能说明
            SQLite驱动通过sql.Register函数在init阶段自动注册到database/sql包中。注册后,开发者使用sql.Open函数通过驱动名称获取数据库连接。这种设计实现了驱动的即插即用,只需导入驱动包即可使用。
        b.代码示例
            ---
            // 驱动注册机制演示
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                // 驱动包的init函数会自动调用sql.Register注册驱动
                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                // 查看已注册的所有驱动
                drivers := sql.Drivers()
                fmt.Println("已注册的数据库驱动:")
                for _, driver := range drivers {
                    fmt.Printf("  - %s\n", driver)
                }

                // 使用已注册的驱动名称打开数据库
                // 驱动名称由驱动包在注册时指定
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal("打开数据库失败:", err)
                }
                defer db.Close()

                // 验证连接
                var version string
                err = db.QueryRow("SELECT sqlite_version()").Scan(&version)
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Printf("SQLite版本: %s\n", version)
            }
            ---

1.2 核心概念

01.嵌入式数据库
    a.概念定义
        a.嵌入式特性
            嵌入式数据库是直接集成到应用程序中运行的数据库系统,无需独立的服务器进程。SQLite作为典型的嵌入式数据库,以库的形式链接到应用程序,数据库引擎与应用共享同一进程空间,消除了进程间通信开销。
        b.文件存储
            SQLite将整个数据库存储在单个磁盘文件中,包括表结构、索引、数据和元信息。文件格式跨平台兼容,可以在不同操作系统和架构之间直接复制使用。文件扩展名通常为.db、.sqlite或.sqlite3。
    b.与服务端数据库对比
        a.架构差异
            ---
            // 嵌入式vs服务端数据库架构对比示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "os"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                // SQLite嵌入式数据库特点演示
                // 1. 无需网络连接,直接操作文件
                dbPath := "./embedded.db"

                // 检查数据库文件是否存在
                if _, err := os.Stat(dbPath); os.IsNotExist(err) {
                    fmt.Println("数据库文件不存在,将自动创建")
                }

                // 2. 连接字符串就是文件路径,无需主机、端口、用户名密码
                db, err := sql.Open("sqlite3", dbPath)
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 3. 数据库引擎在应用进程内运行
                fmt.Printf("进程ID: %d\n", os.Getpid())
                fmt.Println("SQLite引擎运行在同一进程中,无需服务器")

                // 4. 获取数据库文件信息
                fileInfo, err := os.Stat(dbPath)
                if err == nil {
                    fmt.Printf("数据库文件大小: %d bytes\n", fileInfo.Size())
                    fmt.Printf("最后修改时间: %v\n", fileInfo.ModTime())
                }

                // 5. 执行查询验证
                var version string
                db.QueryRow("SELECT sqlite_version()").Scan(&version)
                fmt.Printf("嵌入的SQLite版本: %s\n", version)
            }
            ---
        b.适用场景对比
            嵌入式数据库适合单用户应用、桌面程序、移动应用、物联网设备等场景,数据量通常在GB级别以下。服务端数据库适合多用户并发访问、分布式系统、高可用要求的场景,支持TB甚至PB级别数据存储。

02.连接字符串
    a.基本格式
        a.文件路径模式
            SQLite连接字符串最基本的形式就是数据库文件路径,可以是相对路径或绝对路径。连接时如果文件不存在会自动创建,如果已存在则直接打开。
        b.代码示例
            ---
            // SQLite连接字符串格式示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "os"
                "path/filepath"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                // 相对路径:在当前工作目录创建/打开数据库
                relPath := "./data/app.db"

                // 确保目录存在
                os.MkdirAll(filepath.Dir(relPath), 0755)

                db1, err := sql.Open("sqlite3", relPath)
                if err != nil {
                    log.Fatal(err)
                }
                defer db1.Close()
                fmt.Printf("相对路径数据库: %s\n", relPath)

                // 绝对路径:明确指定数据库位置
                absPath := "/tmp/absolute.db"
                db2, err := sql.Open("sqlite3", absPath)
                if err != nil {
                    log.Fatal(err)
                }
                defer db2.Close()
                fmt.Printf("绝对路径数据库: %s\n", absPath)

                // 获取实际工作目录
                wd, _ := os.Getwd()
                fmt.Printf("当前工作目录: %s\n", wd)
            }
            ---
    b.特殊模式
        a.内存数据库
            a.功能说明
                使用:memory:作为连接字符串可创建内存数据库,数据完全存储在RAM中,连接关闭后数据消失。内存数据库适合临时数据处理、单元测试、缓存场景,访问速度极快。
            b.代码示例
                ---
                // 内存数据库使用示例
                package main

                import (
                    "database/sql"
                    "fmt"
                    "log"

                    _ "github.com/mattn/go-sqlite3"
                )

                func main() {
                    // 创建内存数据库
                    // :memory: 表示数据库完全在内存中
                    db, err := sql.Open("sqlite3", ":memory:")
                    if err != nil {
                        log.Fatal(err)
                    }
                    defer db.Close()

                    // 创建表并插入数据
                    _, err = db.Exec(`
                        CREATE TABLE cache (
                            key TEXT PRIMARY KEY,
                            value TEXT,
                            expires_at INTEGER
                        )
                    `)
                    if err != nil {
                        log.Fatal(err)
                    }

                    // 插入缓存数据
                    _, err = db.Exec(`INSERT INTO cache (key, value) VALUES (?, ?)`,
                        "session:123", `{"user_id": 1, "name": "Alice"}`)
                    if err != nil {
                        log.Fatal(err)
                    }

                    // 查询数据
                    var value string
                    err = db.QueryRow(`SELECT value FROM cache WHERE key = ?`, "session:123").Scan(&value)
                    if err != nil {
                        log.Fatal(err)
                    }
                    fmt.Printf("缓存值: %s\n", value)

                    // 获取内存数据库状态
                    var pageCount, pageSize int
                    db.QueryRow("PRAGMA page_count").Scan(&pageCount)
                    db.QueryRow("PRAGMA page_size").Scan(&pageSize)
                    fmt.Printf("内存占用: 约 %d KB\n", pageCount*pageSize/1024)

                    fmt.Println("注意: 程序结束后,内存数据库中的所有数据将丢失")
                }
                ---
        b.共享内存数据库
            a.功能说明
                普通的:memory:数据库每个连接都是独立的实例。使用file::memory:?mode=memory&cache=shared可以创建多个连接共享的内存数据库,适合需要并发访问内存数据的场景。
            b.代码示例
                ---
                // 共享内存数据库示例
                package main

                import (
                    "database/sql"
                    "fmt"
                    "log"
                    "sync"

                    _ "github.com/mattn/go-sqlite3"
                )

                func main() {
                    // 共享内存数据库连接字符串
                    // cache=shared 允许多个连接共享同一个内存数据库
                    dsn := "file::memory:?mode=memory&cache=shared"

                    // 创建第一个连接并初始化表
                    db1, err := sql.Open("sqlite3", dsn)
                    if err != nil {
                        log.Fatal(err)
                    }
                    defer db1.Close()

                    _, err = db1.Exec(`CREATE TABLE shared_data (id INTEGER PRIMARY KEY, msg TEXT)`)
                    if err != nil {
                        log.Fatal(err)
                    }

                    // 创建第二个连接,共享同一个内存数据库
                    db2, err := sql.Open("sqlite3", dsn)
                    if err != nil {
                        log.Fatal(err)
                    }
                    defer db2.Close()

                    // 并发写入测试
                    var wg sync.WaitGroup
                    for i := 0; i < 5; i++ {
                        wg.Add(1)
                        go func(n int) {
                            defer wg.Done()
                            db := db1
                            if n%2 == 0 {
                                db = db2 // 交替使用两个连接
                            }
                            _, err := db.Exec(`INSERT INTO shared_data (msg) VALUES (?)`,
                                fmt.Sprintf("消息来自goroutine-%d", n))
                            if err != nil {
                                log.Printf("插入失败: %v", err)
                            }
                        }(i)
                    }
                    wg.Wait()

                    // 从任意连接读取数据
                    rows, _ := db2.Query(`SELECT id, msg FROM shared_data ORDER BY id`)
                    defer rows.Close()

                    fmt.Println("共享内存数据库中的数据:")
                    for rows.Next() {
                        var id int
                        var msg string
                        rows.Scan(&id, &msg)
                        fmt.Printf("  ID=%d: %s\n", id, msg)
                    }
                }
                ---

03.DSN参数
    a.连接参数详解
        a.常用参数
            SQLite DSN支持多种参数配置,通过URL查询字符串格式附加在文件路径后。常用参数包括mode(访问模式)、cache(缓存模式)、_journal_mode(日志模式)、_busy_timeout(忙等待超时)等。
        b.代码示例
            ---
            // SQLite DSN参数配置示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "net/url"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                // 构建DSN连接字符串
                // 使用url.Values构建参数,确保正确编码
                params := url.Values{}

                // 访问模式: rwc=读写创建, ro=只读, rw=读写(不创建)
                params.Set("mode", "rwc")

                // 缓存模式: shared=共享缓存, private=私有缓存
                params.Set("cache", "shared")

                // 日志模式: WAL性能更好,DELETE是默认模式
                params.Set("_journal_mode", "WAL")

                // 忙等待超时(毫秒): 遇到锁时等待而非立即返回错误
                params.Set("_busy_timeout", "5000")

                // 同步模式: NORMAL平衡性能和安全性
                params.Set("_synchronous", "NORMAL")

                // 外键约束: 默认关闭,需要显式开启
                params.Set("_foreign_keys", "ON")

                // 组装完整DSN
                dsn := fmt.Sprintf("file:./configured.db?%s", params.Encode())
                fmt.Printf("DSN: %s\n", dsn)

                db, err := sql.Open("sqlite3", dsn)
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 验证配置是否生效
                var journalMode, synchronous string
                var foreignKeys int

                db.QueryRow("PRAGMA journal_mode").Scan(&journalMode)
                db.QueryRow("PRAGMA synchronous").Scan(&synchronous)
                db.QueryRow("PRAGMA foreign_keys").Scan(&foreignKeys)

                fmt.Printf("日志模式: %s\n", journalMode)
                fmt.Printf("同步模式: %s\n", synchronous)
                fmt.Printf("外键约束: %v\n", foreignKeys == 1)
            }
            ---
    b.只读模式
        a.功能说明
            只读模式打开数据库时,任何写入操作都会返回错误。这种模式适合数据分析、报表生成等只需读取数据的场景,可以提高并发性能并防止意外修改数据。
        b.代码示例
            ---
            // 只读模式数据库访问
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "os"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                dbPath := "./readonly_test.db"

                // 首先创建并初始化数据库
                initDB, err := sql.Open("sqlite3", dbPath)
                if err != nil {
                    log.Fatal(err)
                }
                initDB.Exec(`CREATE TABLE IF NOT EXISTS configs (key TEXT, value TEXT)`)
                initDB.Exec(`INSERT OR REPLACE INTO configs VALUES ('version', '1.0.0')`)
                initDB.Close()

                // 以只读模式打开数据库
                // mode=ro 表示只读模式
                dsn := fmt.Sprintf("file:%s?mode=ro", dbPath)
                db, err := sql.Open("sqlite3", dsn)
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 读取操作正常
                var version string
                err = db.QueryRow(`SELECT value FROM configs WHERE key = 'version'`).Scan(&version)
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Printf("读取成功,版本: %s\n", version)

                // 写入操作会失败
                _, err = db.Exec(`INSERT INTO configs VALUES ('new_key', 'new_value')`)
                if err != nil {
                    fmt.Printf("只读模式写入失败(预期行为): %v\n", err)
                }

                // 清理测试文件
                os.Remove(dbPath)
            }
            ---

1.3 优缺点

01.核心优势
    a.零配置部署
        a.功能说明
            SQLite无需安装、配置或管理数据库服务器。只需在Go项目中导入驱动包,即可直接使用数据库功能。数据库文件可以随应用程序一起分发,用户无需任何额外操作即可运行应用。
        b.代码示例
            ---
            // 零配置部署示例:开箱即用的数据库
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "os"
                "path/filepath"

                _ "github.com/mattn/go-sqlite3"
            )

            // AppConfig 应用配置结构
            type AppConfig struct {
                DataDir string
                DBPath  string
            }

            func main() {
                // 自动获取应用数据目录
                homeDir, _ := os.UserHomeDir()
                appDataDir := filepath.Join(homeDir, ".myapp")

                // 自动创建数据目录
                if err := os.MkdirAll(appDataDir, 0755); err != nil {
                    log.Fatal(err)
                }

                // 数据库路径
                dbPath := filepath.Join(appDataDir, "data.db")

                // 打开数据库(自动创建)
                db, err := sql.Open("sqlite3", dbPath)
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 自动初始化表结构
                _, err = db.Exec(`
                    CREATE TABLE IF NOT EXISTS app_settings (
                        key TEXT PRIMARY KEY,
                        value TEXT,
                        updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
                    )
                `)
                if err != nil {
                    log.Fatal(err)
                }

                fmt.Println("应用数据库已就绪")
                fmt.Printf("数据目录: %s\n", appDataDir)
                fmt.Printf("数据库文件: %s\n", dbPath)
                fmt.Println("无需任何额外配置或服务器安装")
            }
            ---
    b.跨平台兼容
        a.功能说明
            SQLite数据库文件��式是跨平台兼容的,在Windows、Linux、macOS等系统之间可以直接复制使用。Go编译的可执行文件可以在不同平台运行,数据库文件也能无缝迁移。
        b.代码示例
            ---
            // 跨平台兼容性检测示例
            package main

            import (
                "database/sql"
                "encoding/binary"
                "fmt"
                "io"
                "log"
                "os"
                "runtime"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                dbPath := "./cross_platform.db"

                // 创建数据库并写入平台信息
                db, err := sql.Open("sqlite3", dbPath)
                if err != nil {
                    log.Fatal(err)
                }

                _, err = db.Exec(`
                    CREATE TABLE IF NOT EXISTS platform_info (
                        id INTEGER PRIMARY KEY,
                        os TEXT,
                        arch TEXT,
                        created_at DATETIME DEFAULT CURRENT_TIMESTAMP
                    )
                `)
                if err != nil {
                    log.Fatal(err)
                }

                // 记录当前平台信息
                _, err = db.Exec(`INSERT INTO platform_info (os, arch) VALUES (?, ?)`,
                    runtime.GOOS, runtime.GOARCH)
                if err != nil {
                    log.Fatal(err)
                }

                db.Close()

                // 读取数据库文件头,验证格式
                file, _ := os.Open(dbPath)
                defer file.Close()

                header := make([]byte, 100)
                io.ReadFull(file, header)

                // SQLite文件头魔数
                magic := string(header[0:16])
                pageSize := binary.BigEndian.Uint16(header[16:18])

                fmt.Printf("当前平台: %s/%s\n", runtime.GOOS, runtime.GOARCH)
                fmt.Printf("SQLite文件头: %s\n", magic)
                fmt.Printf("页面大小: %d bytes\n", pageSize)
                fmt.Println("此数据库文件可在任何支持SQLite的平台上使用")

                os.Remove(dbPath)
            }
            ---
    c.单文件存储
        a.功能说明
            整个数据库(包括多个表、索引、触发器等)都存储在单个文件中,便于备份、迁移和版本控制。可以简单地通过复制文件实现数据库备份,无需复杂的导出导入过程。
        b.代码示例
            ---
            // 单文件存储与备份示例
            package main

            import (
                "database/sql"
                "fmt"
                "io"
                "log"
                "os"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                srcPath := "./source.db"
                backupPath := "./backup.db"

                // 创建源数据库
                srcDB, err := sql.Open("sqlite3", srcPath)
                if err != nil {
                    log.Fatal(err)
                }

                // 创建表和数据
                srcDB.Exec(`CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, price REAL)`)
                srcDB.Exec(`INSERT INTO products (name, price) VALUES ('笔记本', 5999.00)`)
                srcDB.Exec(`INSERT INTO products (name, price) VALUES ('手机', 3999.00)`)
                srcDB.Close()

                // 简单文件复制实现备份
                srcFile, _ := os.Open(srcPath)
                dstFile, _ := os.Create(backupPath)

                bytesCopied, _ := io.Copy(dstFile, srcFile)
                srcFile.Close()
                dstFile.Close()

                fmt.Printf("备份完成,复制了 %d 字节\n", bytesCopied)

                // 验证备份文件
                backupDB, err := sql.Open("sqlite3", backupPath)
                if err != nil {
                    log.Fatal(err)
                }
                defer backupDB.Close()

                var count int
                backupDB.QueryRow(`SELECT COUNT(*) FROM products`).Scan(&count)
                fmt.Printf("备份数据库中有 %d 条产品记录\n", count)

                // 清理
                os.Remove(srcPath)
                os.Remove(backupPath)
            }
            ---

02.主要劣势
    a.并发写入限制
        a.功能说明
            SQLite使用文件级锁,同一时刻只允许一个写入操作。在高并发写入场景下,大量请求会被串行化处理,导致性能瓶颈。WAL模式可以改善读写并发,但写入仍然是串行的。
        b.代码示例
            ---
            // 并发写入限制演示
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "sync"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                // 设置忙等待超时,避免立即返回锁错误
                db, err := sql.Open("sqlite3", "./concurrent.db?_busy_timeout=5000")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                db.Exec(`CREATE TABLE IF NOT EXISTS logs (id INTEGER PRIMARY KEY, msg TEXT, ts DATETIME)`)

                // 模拟并发写入
                var wg sync.WaitGroup
                startTime := time.Now()
                concurrency := 10
                writesPerGoroutine := 100

                for i := 0; i < concurrency; i++ {
                    wg.Add(1)
                    go func(workerID int) {
                        defer wg.Done()
                        for j := 0; j < writesPerGoroutine; j++ {
                            _, err := db.Exec(`INSERT INTO logs (msg, ts) VALUES (?, ?)`,
                                fmt.Sprintf("Worker %d, Write %d", workerID, j),
                                time.Now())
                            if err != nil {
                                log.Printf("写入失败: %v", err)
                            }
                        }
                    }(i)
                }

                wg.Wait()
                elapsed := time.Since(startTime)

                var count int
                db.QueryRow(`SELECT COUNT(*) FROM logs`).Scan(&count)

                fmt.Printf("并发数: %d, 每协程写入: %d\n", concurrency, writesPerGoroutine)
                fmt.Printf("总写入: %d 条, 耗时: %v\n", count, elapsed)
                fmt.Printf("平均每秒写入: %.2f 条\n", float64(count)/elapsed.Seconds())
                fmt.Println("注意: SQLite写入是串行化的,高并发场景需考虑其他方案")
            }
            ---
    b.无网络访问能力
        a.功能说明
            SQLite是嵌入式数据库,只能本地访问,不支持通过网络连接。如果需要多个应用或服务器共享数据,必须借助其他机制如文件共享、API服务或迁移到服务端数据库。
        b.代码示例
            ---
            // 本地访问限制说明示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "net"
                "os"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                // SQLite只能通过文件路径访问
                validPaths := []string{
                    "./local.db",           // 相对路径
                    "/tmp/absolute.db",     // 绝对路径
                    ":memory:",             // 内存数据库
                }

                // 无效的网络连接尝试
                invalidPaths := []string{
                    "tcp://localhost:5432/mydb",   // TCP连接(无效)
                    "postgres://user:pass@host/db", // PostgreSQL风格(无效)
                    "mysql://user:pass@host/db",    // MySQL风格(无效)
                }

                fmt.Println("有效的SQLite连接路径:")
                for _, path := range validPaths {
                    fmt.Printf("  ✓ %s\n", path)
                }

                fmt.Println("\n无效的连接路径(SQLite不支持网络):")
                for _, path := range invalidPaths {
                    fmt.Printf("  ✗ %s\n", path)
                }

                // 如果需要网络访问,可以封装HTTP服务
                fmt.Println("\n解决方案: 通过HTTP API暴露数据库功能")

                // 获取本机IP地址
                addrs, _ := net.InterfaceAddrs()
                for _, addr := range addrs {
                    if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
                        if ipnet.IP.To4() != nil {
                            fmt.Printf("  可在 http://%s:8080/api/data 提供访问\n", ipnet.IP)
                            break
                        }
                    }
                }

                os.Remove("./local.db")
            }
            ---
    c.大规模数据局限
        a.功能说明
            SQLite适合处理GB级别的数据,对于TB级别的大规模数据存储和复杂查询场景,性能和功能可能不足。缺乏分布式能力、高级索引类型和复杂的查询优化器。
        b.代码示例
            ---
            // 数据规模评估示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "os"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", "./scale_test.db")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 获取SQLite的编译限制
                var maxPageCount, pageSize int64
                db.QueryRow("PRAGMA max_page_count").Scan(&maxPageCount)
                db.QueryRow("PRAGMA page_size").Scan(&pageSize)

                // 计算理论最大数据库大小
                maxSizeBytes := maxPageCount * pageSize
                maxSizeGB := float64(maxSizeBytes) / (1024 * 1024 * 1024)
                maxSizeTB := maxSizeGB / 1024

                fmt.Println("SQLite数据规模限制:")
                fmt.Printf("  最大页面数: %d\n", maxPageCount)
                fmt.Printf("  页面大小: %d bytes\n", pageSize)
                fmt.Printf("  理论最大大小: %.2f TB\n", maxSizeTB)

                fmt.Println("\n实际建议:")
                fmt.Println("  ✓ 适合: < 1GB (性能最佳)")
                fmt.Println("  ✓ 可用: 1-10GB (需要优化)")
                fmt.Println("  △ 谨慎: 10-100GB (可能遇到性能问题)")
                fmt.Println("  ✗ 不推荐: > 100GB (应考虑其他数据库)")

                os.Remove("./scale_test.db")
            }
            ---

03.适用性评估
    a.选择决策
        a.功能说明
            选择SQLite需要综合考虑应用场景、数据规模、并发需求和部署环境。以下提供一个简单的决策框架帮助判断SQLite是否适合你的项目。
        b.代码示例
            ---
            // SQLite适用性决策工具
            package main

            import (
                "fmt"
            )

            // RequirementScore 需求评分
            type RequirementScore struct {
                DataSize        int // 数据规模 1-5
                Concurrency     int // 并发需求 1-5
                NetworkAccess   int // 网络访问需求 1-5
                Simplicity      int // 简单性需求 1-5
                Portability     int // 可移植性需求 1-5
            }

            func evaluateSQLiteFit(req RequirementScore) {
                fmt.Println("=== SQLite 适用性评估 ===")

                // SQLite优势项
                advantages := 0
                disadvantages := 0

                // 数据规模评估
                if req.DataSize <= 2 {
                    fmt.Println("✓ 数据规模小,SQLite适合")
                    advantages++
                } else if req.DataSize >= 4 {
                    fmt.Println("✗ 数据规模大,考虑PostgreSQL/MySQL")
                    disadvantages++
                }

                // 并发评估
                if req.Concurrency <= 2 {
                    fmt.Println("✓ 并发需求低,SQLite适合")
                    advantages++
                } else if req.Concurrency >= 4 {
                    fmt.Println("✗ 高并发写入,需要服务端数据库")
                    disadvantages++
                }

                // 网络访问评估
                if req.NetworkAccess <= 2 {
                    fmt.Println("✓ 本地访问为主,SQLite适合")
                    advantages++
                } else {
                    fmt.Println("✗ 需要网络访问,考虑其他方案")
                    disadvantages++
                }

                // 简单性评估
                if req.Simplicity >= 4 {
                    fmt.Println("✓ 追求简单,SQLite零配置优势明显")
                    advantages++
                }

                // 可移植性评估
                if req.Portability >= 4 {
                    fmt.Println("✓ 需要高可移植性,SQLite单文件优势明显")
                    advantages++
                }

                fmt.Printf("\n优势项: %d, 劣势项: %d\n", advantages, disadvantages)
                if advantages > disadvantages {
                    fmt.Println("建议: 使用 SQLite")
                } else {
                    fmt.Println("建议: 考虑其他数据库方案")
                }
            }

            func main() {
                // 示例:评估一个桌面应用
                desktopApp := RequirementScore{
                    DataSize:      1, // 数据量小
                    Concurrency:   1, // 单用户
                    NetworkAccess: 1, // 本地使用
                    Simplicity:    5, // 追求简单
                    Portability:   5, // 需要便携
                }

                fmt.Println("场景: 桌面应用")
                evaluateSQLiteFit(desktopApp)

                fmt.Println("\n" + "=".repeat(40) + "\n")

                // 示例:评估一个Web服务
                webService := RequirementScore{
                    DataSize:      4, // 数据量大
                    Concurrency:   5, // 高并发
                    NetworkAccess: 5, // 网络访问
                    Simplicity:    3, // 中等
                    Portability:   2, // 不重要
                }

                fmt.Println("场景: Web服务后端")
                evaluateSQLiteFit(webService)
            }

            // repeat 重复字符串
            func (s string) repeat(n int) string {
                result := ""
                for i := 0; i < n; i++ {
                    result += s
                }
                return result
            }
            ---

1.4 使用场景

01.桌面应用程序
    a.配置管理
        a.功能说明
            桌面应用通常需要持久化存储用户配置、应用设置和状态信息。SQLite提供比JSON或XML更强大的查询能力,支持复杂的配置关系和条件检索,同时保持轻量级特性。
        b.代码示例
            ---
            // 桌面应用配置管理示例
            package main

            import (
                "database/sql"
                "encoding/json"
                "fmt"
                "log"
                "os"
                "path/filepath"

                _ "github.com/mattn/go-sqlite3"
            )

            // AppSettings 应用设置结构
            type AppSettings struct {
                Theme         string `json:"theme"`
                Language      string `json:"language"`
                AutoSave      bool   `json:"auto_save"`
                SaveInterval  int    `json:"save_interval"`
            }

            // ConfigManager 配置管理器
            type ConfigManager struct {
                db *sql.DB
            }

            func NewConfigManager() (*ConfigManager, error) {
                // 获取用户配置目录
                homeDir, _ := os.UserHomeDir()
                configDir := filepath.Join(homeDir, ".mydesktopapp")
                os.MkdirAll(configDir, 0755)

                db, err := sql.Open("sqlite3", filepath.Join(configDir, "config.db"))
                if err != nil {
                    return nil, err
                }

                // 初始化配置表
                _, err = db.Exec(`
                    CREATE TABLE IF NOT EXISTS app_config (
                        key TEXT PRIMARY KEY,
                        value TEXT,
                        category TEXT,
                        updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
                    )
                `)
                if err != nil {
                    return nil, err
                }

                return &ConfigManager{db: db}, nil
            }

            func (cm *ConfigManager) SaveSettings(settings AppSettings) error {
                data, err := json.Marshal(settings)
                if err != nil {
                    return err
                }

                _, err = cm.db.Exec(`
                    INSERT OR REPLACE INTO app_config (key, value, category)
                    VALUES ('app_settings', ?, 'general')`,
                    string(data))
                return err
            }

            func (cm *ConfigManager) LoadSettings() (*AppSettings, error) {
                var data string
                err := cm.db.QueryRow(`SELECT value FROM app_config WHERE key = 'app_settings'`).Scan(&data)
                if err == sql.ErrNoRows {
                    // 返回默认设置
                    return &AppSettings{
                        Theme:        "light",
                        Language:     "zh-CN",
                        AutoSave:     true,
                        SaveInterval: 300,
                    }, nil
                }
                if err != nil {
                    return nil, err
                }

                var settings AppSettings
                err = json.Unmarshal([]byte(data), &settings)
                return &settings, err
            }

            func (cm *ConfigManager) Close() error {
                return cm.db.Close()
            }

            func main() {
                cm, err := NewConfigManager()
                if err != nil {
                    log.Fatal(err)
                }
                defer cm.Close()

                // 保存设置
                settings := AppSettings{
                    Theme:        "dark",
                    Language:     "en-US",
                    AutoSave:     true,
                    SaveInterval: 600,
                }
                cm.SaveSettings(settings)

                // 加载设置
                loaded, _ := cm.LoadSettings()
                fmt.Printf("当前配置: 主题=%s, 语言=%s, 自动保存=%v\n",
                    loaded.Theme, loaded.Language, loaded.AutoSave)
            }
            ---
    b.本地缓存
        a.功能说明
            桌面应用可以使用SQLite缓存从服务器下载的数据,实现离线访问和快速响应。相比内存缓存,SQLite提供持久化能力,应用重启后数据仍然可用。
        b.代码示例
            ---
            // 桌面应用本地缓存示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            // CacheItem 缓存项
            type CacheItem struct {
                Key       string
                Value     string
                ExpiresAt time.Time
            }

            // LocalCache 本地缓存管理器
            type LocalCache struct {
                db *sql.DB
            }

            func NewLocalCache(dbPath string) (*LocalCache, error) {
                db, err := sql.Open("sqlite3", dbPath)
                if err != nil {
                    return nil, err
                }

                _, err = db.Exec(`
                    CREATE TABLE IF NOT EXISTS cache (
                        key TEXT PRIMARY KEY,
                        value TEXT,
                        expires_at INTEGER,
                        created_at INTEGER DEFAULT (strftime('%s', 'now'))
                    )
                `)
                if err != nil {
                    return nil, err
                }

                // 创建过期时间索引
                db.Exec(`CREATE INDEX IF NOT EXISTS idx_expires ON cache(expires_at)`)

                return &LocalCache{db: db}, nil
            }

            func (lc *LocalCache) Set(key, value string, ttl time.Duration) error {
                expiresAt := time.Now().Add(ttl).Unix()
                _, err := lc.db.Exec(`
                    INSERT OR REPLACE INTO cache (key, value, expires_at)
                    VALUES (?, ?, ?)`,
                    key, value, expiresAt)
                return err
            }

            func (lc *LocalCache) Get(key string) (string, bool, error) {
                var value string
                var expiresAt int64

                err := lc.db.QueryRow(`
                    SELECT value, expires_at FROM cache WHERE key = ?`, key).Scan(&value, &expiresAt)

                if err == sql.ErrNoRows {
                    return "", false, nil
                }
                if err != nil {
                    return "", false, err
                }

                // 检查是否过期
                if time.Now().Unix() > expiresAt {
                    lc.db.Exec(`DELETE FROM cache WHERE key = ?`, key)
                    return "", false, nil
                }

                return value, true, nil
            }

            func (lc *LocalCache) CleanExpired() (int64, error) {
                result, err := lc.db.Exec(`DELETE FROM cache WHERE expires_at < ?`, time.Now().Unix())
                if err != nil {
                    return 0, err
                }
                return result.RowsAffected()
            }

            func main() {
                cache, err := NewLocalCache(":memory:")
                if err != nil {
                    log.Fatal(err)
                }

                // 缓存数据(5秒有效期)
                cache.Set("user:123", `{"name": "Alice", "age": 30}`, 5*time.Second)

                // 立即读取
                if value, found, _ := cache.Get("user:123"); found {
                    fmt.Printf("缓存命中: %s\n", value)
                }

                // 等待过期
                time.Sleep(6 * time.Second)

                // 过期后读取
                if _, found, _ := cache.Get("user:123"); !found {
                    fmt.Println("缓存已过期")
                }

                // 清理过期数据
                deleted, _ := cache.CleanExpired()
                fmt.Printf("清理了 %d 条过期缓存\n", deleted)
            }
            ---

02.移动应用后端
    a.数据同步
        a.功能说明
            移动应用可以使用SQLite作为本地数据库,存储从服务器同步的数据。支持增量同步、冲突解决和离线编辑,用户在无网络环境下也能正常使用应用。
        b.代码示例
            ---
            // 移动应用数据同步管理示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            // SyncRecord 同步记录
            type SyncRecord struct {
                ID           int64
                ResourceType string
                ResourceID   string
                Action       string // create, update, delete
                Data         string
                SyncStatus   string // pending, synced, failed
                CreatedAt    time.Time
            }

            // SyncManager 同步管理器
            type SyncManager struct {
                db *sql.DB
            }

            func NewSyncManager(dbPath string) (*SyncManager, error) {
                db, err := sql.Open("sqlite3", dbPath)
                if err != nil {
                    return nil, err
                }

                _, err = db.Exec(`
                    CREATE TABLE IF NOT EXISTS sync_queue (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        resource_type TEXT NOT NULL,
                        resource_id TEXT NOT NULL,
                        action TEXT NOT NULL,
                        data TEXT,
                        sync_status TEXT DEFAULT 'pending',
                        created_at INTEGER DEFAULT (strftime('%s', 'now')),
                        synced_at INTEGER
                    )
                `)
                if err != nil {
                    return nil, err
                }

                db.Exec(`CREATE INDEX IF NOT EXISTS idx_sync_status ON sync_queue(sync_status)`)

                return &SyncManager{db: db}, nil
            }

            func (sm *SyncManager) AddToQueue(record SyncRecord) error {
                _, err := sm.db.Exec(`
                    INSERT INTO sync_queue (resource_type, resource_id, action, data)
                    VALUES (?, ?, ?, ?)`,
                    record.ResourceType, record.ResourceID, record.Action, record.Data)
                return err
            }

            func (sm *SyncManager) GetPendingRecords(limit int) ([]SyncRecord, error) {
                rows, err := sm.db.Query(`
                    SELECT id, resource_type, resource_id, action, data, created_at
                    FROM sync_queue
                    WHERE sync_status = 'pending'
                    ORDER BY created_at
                    LIMIT ?`, limit)
                if err != nil {
                    return nil, err
                }
                defer rows.Close()

                var records []SyncRecord
                for rows.Next() {
                    var r SyncRecord
                    var createdAt int64
                    rows.Scan(&r.ID, &r.ResourceType, &r.ResourceID, &r.Action, &r.Data, &createdAt)
                    r.CreatedAt = time.Unix(createdAt, 0)
                    records = append(records, r)
                }
                return records, nil
            }

            func (sm *SyncManager) MarkAsSynced(id int64) error {
                _, err := sm.db.Exec(`
                    UPDATE sync_queue
                    SET sync_status = 'synced', synced_at = strftime('%s', 'now')
                    WHERE id = ?`, id)
                return err
            }

            func main() {
                sm, err := NewSyncManager(":memory:")
                if err != nil {
                    log.Fatal(err)
                }

                // 添加待同步的变更
                sm.AddToQueue(SyncRecord{
                    ResourceType: "note",
                    ResourceID:   "note-123",
                    Action:       "update",
                    Data:         `{"title": "会议记录", "content": "..."}`,
                })

                sm.AddToQueue(SyncRecord{
                    ResourceType: "note",
                    ResourceID:   "note-456",
                    Action:       "create",
                    Data:         `{"title": "待办事项", "content": "..."}`,
                })

                // 获取待同步记录
                pending, _ := sm.GetPendingRecords(10)
                fmt.Printf("待同步记录数: %d\n", len(pending))

                // 模拟同步完成
                for _, record := range pending {
                    fmt.Printf("正在同步: %s %s\n", record.Action, record.ResourceID)
                    sm.MarkAsSynced(record.ID)
                }

                // 验证同步状态
                remaining, _ := sm.GetPendingRecords(10)
                fmt.Printf("剩余待同步: %d\n", len(remaining))
            }
            ---

03.嵌入式系统
    a.物联网设备
        a.功能说明
            SQLite适合在资源受限的物联网设备上运行,存储传感器数据、设备日志和配置信息。低内存占用和无服务器架构非常适合边缘计算场景。
        b.代码示例
            ---
            // 物联网设备数据采集示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "math/rand"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            // SensorReading 传感器读数
            type SensorReading struct {
                SensorID    string
                Temperature float64
                Humidity    float64
                Timestamp   time.Time
            }

            // IoTDataCollector 物联网数据采集器
            type IoTDataCollector struct {
                db *sql.DB
            }

            func NewIoTDataCollector(dbPath string) (*IoTDataCollector, error) {
                // 使用WAL模式提高写入性能
                db, err := sql.Open("sqlite3", fmt.Sprintf("%s?_journal_mode=WAL", dbPath))
                if err != nil {
                    return nil, err
                }

                _, err = db.Exec(`
                    CREATE TABLE IF NOT EXISTS sensor_data (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        sensor_id TEXT NOT NULL,
                        temperature REAL,
                        humidity REAL,
                        timestamp INTEGER NOT NULL
                    )
                `)
                if err != nil {
                    return nil, err
                }

                // 创建时间索引用于时间范围查询
                db.Exec(`CREATE INDEX IF NOT EXISTS idx_timestamp ON sensor_data(timestamp)`)

                return &IoTDataCollector{db: db}, nil
            }

            func (idc *IoTDataCollector) RecordReading(reading SensorReading) error {
                _, err := idc.db.Exec(`
                    INSERT INTO sensor_data (sensor_id, temperature, humidity, timestamp)
                    VALUES (?, ?, ?, ?)`,
                    reading.SensorID, reading.Temperature, reading.Humidity, reading.Timestamp.Unix())
                return err
            }

            func (idc *IoTDataCollector) GetAverages(sensorID string, since time.Time) (float64, float64, error) {
                var avgTemp, avgHumidity float64
                err := idc.db.QueryRow(`
                    SELECT AVG(temperature), AVG(humidity)
                    FROM sensor_data
                    WHERE sensor_id = ? AND timestamp >= ?`,
                    sensorID, since.Unix()).Scan(&avgTemp, &avgHumidity)
                return avgTemp, avgHumidity, err
            }

            func (idc *IoTDataCollector) PurgeOldData(before time.Time) (int64, error) {
                result, err := idc.db.Exec(`DELETE FROM sensor_data WHERE timestamp < ?`, before.Unix())
                if err != nil {
                    return 0, err
                }
                return result.RowsAffected()
            }

            func main() {
                collector, err := NewIoTDataCollector(":memory:")
                if err != nil {
                    log.Fatal(err)
                }

                // 模拟传感器数据采集
                sensorID := "temp-sensor-001"
                for i := 0; i < 100; i++ {
                    reading := SensorReading{
                        SensorID:    sensorID,
                        Temperature: 20.0 + rand.Float64()*10.0,
                        Humidity:    50.0 + rand.Float64()*30.0,
                        Timestamp:   time.Now().Add(-time.Duration(i) * time.Minute),
                    }
                    collector.RecordReading(reading)
                }

                // 计算最近1小时的平均值
                avgTemp, avgHumidity, _ := collector.GetAverages(sensorID, time.Now().Add(-1*time.Hour))
                fmt.Printf("最近1小时平均: 温度=%.2f°C, 湿度=%.2f\n", utilization)
            }
            ---
    b.B-Tree索引
        a.功能说明
            SQLite使用B-Tree数据结构存储表数据和索引。每个表对应一棵B-Tree,主键为隐式索引。B-Tree的节点存储在页面中,支持范围查询和顺序扫描,平衡树保证O(log N)的查询性能。
        b.代码示例
            ---
            // B-Tree索引性能对比
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "math/rand"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 创建测试表
                db.Exec(`CREATE TABLE users (
                    id INTEGER PRIMARY KEY,
                    name TEXT,
                    age INTEGER,
                    email TEXT
                )`)

                // 插入测试数据
                stmt, _ := db.Prepare(`INSERT INTO users (name, age, email) VALUES (?, ?, ?)`)
                for i := 0; i < 10000; i++ {
                    stmt.Exec(
                        fmt.Sprintf("User%d", i),
                        rand.Intn(80)+18,
                        fmt.Sprintf("user%[email protected]", i),
                    )
                }
                stmt.Close()

                // 无索引查询
                start := time.Now()
                var count int
                db.QueryRow(`SELECT COUNT(*) FROM users WHERE age > 50`).Scan(&count)
                noIndexTime := time.Since(start)
                fmt.Printf("无索引查询: %v, 结果: %d条\n", noIndexTime, count)

                // 创建索引
                db.Exec(`CREATE INDEX idx_age ON users(age)`)

                // 有索引查询
                start = time.Now()
                db.QueryRow(`SELECT COUNT(*) FROM users WHERE age > 50`).Scan(&count)
                withIndexTime := time.Since(start)
                fmt.Printf("有索引查询: %v, 结果: %d条\n", withIndexTime, count)

                // 性能提升
                improvement := float64(noIndexTime) / float64(withIndexTime)
                fmt.Printf("性能提升: %.2fx\n", improvement)

                // 查看索引详情
                rows, _ := db.Query(`SELECT name, rootpage FROM sqlite_master WHERE type = 'index'`)
                fmt.Println("\n索引列表:")
                for rows.Next() {
                    var name string
                    var rootpage int
                    rows.Scan(&name, &rootpage)
                    fmt.Printf("  - %s (根页面: %d)\n", name, rootpage)
                }
            }
            ---

03.事务机制
    a.日志模式
        a.回滚日志(Rollback Journal)
            a.工作原理
                回滚日志是SQLite默认的事务实现方式。在修改数据库页面前,先将原始页面内容写入日志文件。如果事务失败,通过回滚日志恢复数据。事务提交后删除日志文件。
            b.代码示例
                ---
                // 回滚日志模式演示
                package main

                import (
                    "database/sql"
                    "fmt"
                    "log"
                    "os"

                    _ "github.com/mattn/go-sqlite3"
                )

                func main() {
                    dbPath := "./rollback_test.db"
                    journalPath := dbPath + "-journal"

                    // 删除旧文件
                    os.Remove(dbPath)
                    os.Remove(journalPath)

                    db, err := sql.Open("sqlite3", dbPath)
                    if err != nil {
                        log.Fatal(err)
                    }
                    defer db.Close()

                    // 确认使用DELETE模式(回滚日志)
                    var journalMode string
                    db.QueryRow("PRAGMA journal_mode").Scan(&journalMode)
                    fmt.Printf("日志模式: %s\n", journalMode)

                    db.Exec(`CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance REAL)`)
                    db.Exec(`INSERT INTO accounts (balance) VALUES (1000.00)`)

                    // 开始事务
                    tx, _ := db.Begin()

                    // 执行更新
                    tx.Exec(`UPDATE accounts SET balance = balance - 100 WHERE id = 1`)

                    // 检查日志文件是否生成
                    if _, err := os.Stat(journalPath); err == nil {
                        info, _ := os.Stat(journalPath)
                        fmt.Printf("日志文件已创建: %s (%d bytes)\n", journalPath, info.Size())
                    } else {
                        fmt.Println("日志文件未创建(可能被优化)")
                    }

                    // 回滚事务
                    tx.Rollback()
                    fmt.Println("事务已回滚")

                    // 验证数据未改变
                    var balance float64
                    db.QueryRow(`SELECT balance FROM accounts WHERE id = 1`).Scan(&balance)
                    fmt.Printf("余额: %.2f (应为1000.00)\n", balance)

                    // 检查日志文件是否删除
                    if _, err := os.Stat(journalPath); os.IsNotExist(err) {
                        fmt.Println("日志文件已删除")
                    }

                    os.Remove(dbPath)
                }
                ---
        b.WAL模式(Write-Ahead Logging)
            a.工作原理
                WAL模式将修改先写入WAL文件,而不直接修改数据库文件。读操作可以读取原始数据库文件,写操作追加到WAL文件,实现读写并发。定期执行checkpoint将WAL合并回数据库。
            b.代码示例
                ---
                // WAL模式性能对比
                package main

                import (
                    "database/sql"
                    "fmt"
                    "log"
                    "sync"
                    "time"

                    _ "github.com/mattn/go-sqlite3"
                )

                func benchmarkMode(dsn string, modeName string) {
                    db, err := sql.Open("sqlite3", dsn)
                    if err != nil {
                        log.Fatal(err)
                    }
                    defer db.Close()

                    db.Exec(`CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)`)

                    // 并发读写测试
                    var wg sync.WaitGroup
                    start := time.Now()

                    // 1个写协程
                    wg.Add(1)
                    go func() {
                        defer wg.Done()
                        for i := 0; i < 1000; i++ {
                            db.Exec(`INSERT INTO test (value) VALUES (?)`, fmt.Sprintf("value%d", i))
                        }
                    }()

                    // 5个读协程
                    for j := 0; j < 5; j++ {
                        wg.Add(1)
                        go func() {
                            defer wg.Done()
                            for i := 0; i < 200; i++ {
                                var count int
                                db.QueryRow(`SELECT COUNT(*) FROM test`).Scan(&count)
                            }
                        }()
                    }

                    wg.Wait()
                    elapsed := time.Since(start)
                    fmt.Printf("%s 模式: 耗时 %v\n", modeName, elapsed)
                }

                func main() {
                    fmt.Println("测试DELETE模式(回滚日志):")
                    benchmarkMode(":memory:", "DELETE")

                    fmt.Println("\n测试WAL模式:")
                    benchmarkMode(":memory:?_journal_mode=WAL", "WAL")

                    fmt.Println("\nWAL模式优势:")
                    fmt.Println("  1. 读写可以并发")
                    fmt.Println("  2. 写入性能更好(追加而非修改)")
                    fmt.Println("  3. 更好的崩溃恢复")
                    fmt.Println("  4. 适合高并发读场景")
                }
                ---
    b.ACID特性
        a.功能说明
            SQLite通过日志机制、锁和页面缓存实现ACID特性。原子性通过事务保证,一致性通过约束检查,隔离性通过锁机制,持久性通过fsync确保数据落盘。
        b.代码示例
            ---
            // ACID特性验证
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 创建测试表
                db.Exec(`CREATE TABLE accounts (
                    id INTEGER PRIMARY KEY,
                    name TEXT NOT NULL,
                    balance REAL CHECK(balance >= 0)
                )`)

                db.Exec(`INSERT INTO accounts (name, balance) VALUES ('Alice', 1000)`)
                db.Exec(`INSERT INTO accounts (name, balance) VALUES ('Bob', 500)`)

                fmt.Println("=== ACID特性演示 ===\n")

                // 1. 原子性(Atomicity)
                fmt.Println("1. 原子性: 转账100元")
                tx, _ := db.Begin()
                tx.Exec(`UPDATE accounts SET balance = balance - 100 WHERE name = 'Alice'`)
                tx.Exec(`UPDATE accounts SET balance = balance + 100 WHERE name = 'Bob'`)

                // 模拟异常,回滚事务
                tx.Rollback()
                fmt.Println("   事务回滚,所有操作撤销")

                var aliceBalance, bobBalance float64
                db.QueryRow(`SELECT balance FROM accounts WHERE name = 'Alice'`).Scan(&aliceBalance)
                db.QueryRow(`SELECT balance FROM accounts WHERE name = 'Bob'`).Scan(&bobBalance)
                fmt.Printf("   Alice: %.2f, Bob: %.2f (未改变)\n\n", aliceBalance, bobBalance)

                // 2. 一致性(Consistency)
                fmt.Println("2. 一致性: 尝试设置负余额")
                _, err = db.Exec(`UPDATE accounts SET balance = -100 WHERE name = 'Alice'`)
                if err != nil {
                    fmt.Printf("   违反约束,操作被拒绝: %v\n\n", err)
                }

                // 3. 隔离性(Isolation)
                fmt.Println("3. 隔离性: 事务隔离级别")
                var isolationLevel string
                db.QueryRow(`PRAGMA read_uncommitted`).Scan(&isolationLevel)
                fmt.Printf("   当前隔离级别: %s\n\n", isolationLevel)

                // 4. 持久性(Durability)
                fmt.Println("4. 持久性: 成功提交的事务")
                tx, _ = db.Begin()
                tx.Exec(`UPDATE accounts SET balance = balance + 50 WHERE name = 'Alice'`)
                tx.Commit()
                fmt.Println("   事务提交,数据持久化保存")

                db.QueryRow(`SELECT balance FROM accounts WHERE name = 'Alice'`).Scan(&aliceBalance)
                fmt.Printf("   Alice新余额: %.2f\n", aliceBalance)
            }
            ---

04.锁机制
    a.锁级别
        a.功能说明
            SQLite使用5级锁机制:UNLOCKED(无锁)、SHARED(共享锁,多个读)、RESERVED(预留锁,准备写)、PENDING(等待锁,准备排他)、EXCLUSIVE(排他锁,独占写入)。锁的粒度是整个数据库文件。
        b.代码示例
            ---
            // 锁机制演示
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "sync"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                dbPath := "./lock_test.db"
                dsn := fmt.Sprintf("%s?_busy_timeout=5000", dbPath)

                db1, _ := sql.Open("sqlite3", dsn)
                defer db1.Close()

                db2, _ := sql.Open("sqlite3", dsn)
                defer db2.Close()

                db1.Exec(`CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, value TEXT)`)

                fmt.Println("=== SQLite锁机制演示 ===\n")

                // 场景1: 多个读锁可以共存
                fmt.Println("场景1: 并发读取(SHARED锁)")
                var wg sync.WaitGroup
                for i := 0; i < 3; i++ {
                    wg.Add(1)
                    go func(n int) {
                        defer wg.Done()
                        tx, _ := db1.Begin()
                        defer tx.Rollback()

                        var count int
                        tx.QueryRow(`SELECT COUNT(*) FROM test`).Scan(&count)
                        fmt.Printf("  读操作%d: 成功获取SHARED锁\n", n)
                        time.Sleep(100 * time.Millisecond)
                    }(i)
                }
                wg.Wait()
                fmt.Println()

                // 场景2: 写锁互斥
                fmt.Println("场景2: 并发写入(EXCLUSIVE锁)")
                tx1, _ := db1.Begin()
                fmt.Println("  连接1: 开始事务,获取RESERVED锁")

                tx1.Exec(`INSERT INTO test (value) VALUES ('data1')`)
                fmt.Println("  连接1: 执行写入,升级到EXCLUSIVE锁")

                // 另一个连接尝试写入
                done := make(chan bool)
                go func() {
                    fmt.Println("  连接2: 尝试写入...")
                    _, err := db2.Exec(`INSERT INTO test (value) VALUES ('data2')`)
                    if err != nil {
                        fmt.Printf("  连接2: 等待锁超时或失败: %v\n", err)
                    } else {
                        fmt.Println("  连接2: 写入成功")
                    }
                    done <- true
                }()

                time.Sleep(500 * time.Millisecond)
                tx1.Commit()
                fmt.Println("  连接1: 提交事务,释放EXCLUSIVE锁")

                <-done
                fmt.Println("\n锁机制总结:")
                fmt.Println("  - 多个SHARED锁可以共存(并发读)")
                fmt.Println("  - EXCLUSIVE锁独占(写操作互斥)")
                fmt.Println("  - 锁粒度是整个数据库文件")
            }
            ---

1.6 CGO依赖

01.CGO机制
    a.基本概念
        a.功能说明
            CGO是Go语言调用C代码的机制。go-sqlite3驱动通过CGO直接调用SQLite的C库函数,实现高性能的数据库操作。CGO允许Go代码中嵌入C代码,通过特殊的注释标记和类型转换实现互操作。
        b.代码示例
            ---
            // CGO机制说明示例
            package main

            /*
            #cgo CFLAGS: -DSQLITE_ENABLE_FTS5
            #include <sqlite3.h>
            #include <stdlib.h>

            // C函数包装器示例
            static int get_sqlite_version_number() {
                return sqlite3_libversion_number();
            }
            */
            import "C"
            import (
                "database/sql"
                "fmt"
                "log"
                "unsafe"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                fmt.Println("=== CGO机制演示 ===\n")

                // 通过CGO直接调用SQLite C函数
                versionNum := C.get_sqlite_version_number()
                fmt.Printf("SQLite版本号(通过CGO): %d\n", versionNum)

                // 通过CGO获取版本字符串
                cVersion := C.sqlite3_libversion()
                goVersion := C.GoString(cVersion)
                fmt.Printf("SQLite版本(C字符串): %s\n", goVersion)

                // 通过database/sql获取版本(内部也是用CGO)
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                var sqlVersion string
                db.QueryRow("SELECT sqlite_version()").Scan(&sqlVersion)
                fmt.Printf("SQLite版本(SQL查询): %s\n", sqlVersion)

                // 演示CGO的类型转换
                fmt.Println("\nCGO类型转换:")
                fmt.Printf("  C.int -> Go int: %T\n", int(versionNum))
                fmt.Printf("  *C.char -> Go string: %T\n", goVersion)

                // 内存管理示例
                cString := C.CString("Hello from Go")
                defer C.free(unsafe.Pointer(cString))
                fmt.Printf("  Go string -> *C.char: %p\n", cString)
            }
            ---
    b.编译要求
        a.功能说明
            使用go-sqlite3需要C编译器环境。Linux和macOS通常自带gcc或clang,Windows需要安装MinGW或TDM-GCC。编译时CGO默认启用,可通过CGO_ENABLED环境变量控制。
        b.代码示例
            ---
            // 检测CGO编译环境
            package main

            import (
                "fmt"
                "os"
                "os/exec"
                "runtime"
                "strings"
            )

            func main() {
                fmt.Println("=== CGO编译环境检测 ===\n")

                // 检查CGO是否启用
                cgoEnabled := os.Getenv("CGO_ENABLED")
                if cgoEnabled == "" {
                    cgoEnabled = "1" // 默认启用
                }
                fmt.Printf("CGO_ENABLED: %s (%s)\n",
                    cgoEnabled,
                    map[string]string{"0": "禁用", "1": "启用"}[cgoEnabled])

                // 检查C编译器
                fmt.Println("\nC编译器检测:")
                compilers := []string{"gcc", "clang", "cc"}
                var foundCompiler string

                for _, compiler := range compilers {
                    cmd := exec.Command(compiler, "--version")
                    output, err := cmd.CombinedOutput()
                    if err == nil {
                        foundCompiler = compiler
                        lines := strings.Split(string(output), "\n")
                        fmt.Printf("  ✓ %s: %s\n", compiler, lines[0])
                        break
                    }
                }

                if foundCompiler == "" {
                    fmt.Println("  ✗ 未找到C编译器")
                    fmt.Println("\n安装建议:")
                    switch runtime.GOOS {
                    case "linux":
                        fmt.Println("  sudo apt install gcc  # Debian/Ubuntu")
                        fmt.Println("  sudo yum install gcc  # CentOS/RHEL")
                    case "darwin":
                        fmt.Println("  xcode-select --install")
                    case "windows":
                        fmt.Println("  下载安装 TDM-GCC: https://jmeubank.github.io/tdm-gcc/")
                        fmt.Println("  或使用 MinGW: https://www.mingw-w64.org/")
                    }
                }

                // 平台信息
                fmt.Printf("\n平台信息:\n")
                fmt.Printf("  OS: %s\n", runtime.GOOS)
                fmt.Printf("  架构: %s\n", runtime.GOARCH)
                fmt.Printf("  Go版本: %s\n", runtime.Version())

                // 编译标签示例
                fmt.Println("\n编译go-sqlite3的命令:")
                fmt.Println("  go build -tags \"fts5\"  # 启用全文搜索")
                fmt.Println("  go build -tags \"json1\" # 启用JSON支持")
            }
            ---

02.编译选项
    a.构建标签
        a.功能说明
            go-sqlite3支持多种构建标签(build tags)来启用SQLite的可选功能。常用标签包括fts5(全文搜索)、json1(JSON函数)、icu(国际化)等。通过-tags参数在编译时指定。
        b.代码示例
            ---
            // 构建标签功能测试
            // 编译命令: go run -tags "fts5 json1" main.go
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                fmt.Println("=== SQLite编译选项检测 ===\n")

                // 检查FTS5支持(全文搜索)
                fmt.Println("1. FTS5全文搜索:")
                _, err = db.Exec(`CREATE VIRTUAL TABLE docs USING fts5(content)`)
                if err != nil {
                    fmt.Printf("   ✗ FTS5未启用: %v\n", err)
                    fmt.Println("   编译时添加: -tags fts5")
                } else {
                    fmt.Println("   ✓ FTS5已启用")
                    db.Exec(`INSERT INTO docs VALUES ('Go语言数据库编程')`)
                    db.Exec(`INSERT INTO docs VALUES ('SQLite全文搜索教程')`)

                    var result string
                    db.QueryRow(`SELECT content FROM docs WHERE docs MATCH '数据库'`).Scan(&result)
                    fmt.Printf("   搜索结果: %s\n", result)
                }

                // 检查JSON1支持
                fmt.Println("\n2. JSON1函数:")
                var jsonResult string
                err = db.QueryRow(`SELECT json('{"name": "Alice"}')`).Scan(&jsonResult)
                if err != nil {
                    fmt.Printf("   ✗ JSON1未启用: %v\n", err)
                    fmt.Println("   编译时添加: -tags json1")
                } else {
                    fmt.Printf("   ✓ JSON1已启用: %s\n", jsonResult)

                    // JSON提取示例
                    var name string
                    db.QueryRow(`SELECT json_extract('{"name": "Bob", "age": 30}', '$.name')`).Scan(&name)
                    fmt.Printf("   JSON提取: %s\n", name)
                }

                // 检查其他编译选项
                fmt.Println("\n3. 其他可用选项:")
                options := map[string]string{
                    "fts5":              "全文搜索引擎",
                    "json1":             "JSON函数支持",
                    "icu":               "国际化排序",
                    "foreign_keys":      "外键约束(默认启用)",
                    "secure_delete":     "安全删除",
                    "unlock_notify":     "解锁通知",
                    "vtable":            "虚拟表支持",
                }

                for tag, desc := range options {
                    fmt.Printf("   -tags %s: %s\n", tag, desc)
                }
            }
            ---
    b.性能优化标签
        a.功能说明
            通过编译标签可以优化SQLite性能。例如libsqlite3启用系统SQLite库,omit_load_extension禁用扩展加载提高安全性,sqlite_stat4启用更精确的查询优化器统计。
        b.代码示例
            ---
            // 性能优化编译标签示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func benchmark(db *sql.DB, name string) time.Duration {
                start := time.Now()

                // 创建测试表
                db.Exec(`CREATE TABLE IF NOT EXISTS benchmark (id INTEGER PRIMARY KEY, data TEXT)`)

                // 插入测试数据
                tx, _ := db.Begin()
                stmt, _ := tx.Prepare(`INSERT INTO benchmark (data) VALUES (?)`)
                for i := 0; i < 10000; i++ {
                    stmt.Exec(fmt.Sprintf("数据%d", i))
                }
                stmt.Close()
                tx.Commit()

                // 查询测试
                for i := 0; i < 1000; i++ {
                    var count int
                    db.QueryRow(`SELECT COUNT(*) FROM benchmark WHERE id > ?`, i).Scan(&count)
                }

                return time.Since(start)
            }

            func main() {
                fmt.Println("=== 性能优化编译标签 ===\n")

                // 标准编译版本
                db1, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db1.Close()

                elapsed := benchmark(db1, "标准版本")
                fmt.Printf("标准编译版本: %v\n", elapsed)

                fmt.Println("\n推荐的性能优化编译选项:")
                fmt.Println("1. 使用系统SQLite库:")
                fmt.Println("   go build -tags \"libsqlite3\"")
                fmt.Println("   优势: 可能更新,系统优化")
                fmt.Println()

                fmt.Println("2. 禁用不需要的功能:")
                fmt.Println("   go build -tags \"sqlite_omit_load_extension\"")
                fmt.Println("   优势: 减小二进制大小,提高安全性")
                fmt.Println()

                fmt.Println("3. 启用查询优化:")
                fmt.Println("   go build -tags \"sqlite_stat4\"")
                fmt.Println("   优势: 更准确的查询计划")
                fmt.Println()

                fmt.Println("4. 组合使用:")
                fmt.Println("   go build -tags \"fts5 json1 sqlite_stat4\"")
                fmt.Println("   优势: 功能+性能兼顾")
            }
            ---

03.跨平台编译
    a.交叉编译挑战
        a.功能说明
            由于go-sqlite3依赖CGO,交叉编译需要目标平台的C交叉编译器。例如从Linux编译Windows程序需要mingw-w64,这增加了构建复杂度。纯Go的modernc-sqlite可以避免此问题。
        b.代码示例
            ---
            // 跨平台编译脚本生成器
            package main

            import (
                "fmt"
                "runtime"
            )

            type BuildTarget struct {
                GOOS   string
                GOARCH string
                CC     string
                Desc   string
            }

            func main() {
                fmt.Println("=== go-sqlite3跨平台编译指南 ===\n")
                fmt.Printf("当前平台: %s/%s\n\n", runtime.GOOS, runtime.GOARCH)

                targets := []BuildTarget{
                    {"linux", "amd64", "gcc", "Linux 64位"},
                    {"linux", "arm64", "aarch64-linux-gnu-gcc", "Linux ARM64"},
                    {"windows", "amd64", "x86_64-w64-mingw32-gcc", "Windows 64位"},
                    {"darwin", "amd64", "o64-clang", "macOS Intel"},
                    {"darwin", "arm64", "oa64-clang", "macOS Apple Silicon"},
                }

                fmt.Println("编译命令:")
                for i, target := range targets {
                    fmt.Printf("\n%d. %s (%s/%s):\n", i+1, target.Desc, target.GOOS, target.GOARCH)

                    if target.GOOS == "windows" {
                        fmt.Println("   # 需要安装mingw-w64")
                        fmt.Println("   # Ubuntu: sudo apt install mingw-w64")
                    } else if target.GOARCH == "arm64" && target.GOOS == "linux" {
                        fmt.Println("   # 需要安装ARM交叉编译器")
                        fmt.Println("   # Ubuntu: sudo apt install gcc-aarch64-linux-gnu")
                    }

                    fmt.Printf("   CGO_ENABLED=1 GOOS=%s GOARCH=%s CC=%s go build -o app_%s_%s\n",
                        target.GOOS, target.GOARCH, target.CC, target.GOOS, target.GOARCH)
                }

                fmt.Println("\n纯Go方案(无需交叉编译器):")
                fmt.Println("   使用 modernc.org/sqlite 替代 go-sqlite3")
                fmt.Println("   GOOS=windows GOARCH=amd64 go build  # 直接编译,无需CGO")
                fmt.Println()

                fmt.Println("Docker构建方案:")
                fmt.Println("   使用包含交叉编译器的Docker镜像")
                fmt.Println("   docker run --rm -v \"$PWD\":/usr/src/myapp -w /usr/src/myapp \\")
                fmt.Println("     golang:1.21 go build -v")
            }
            ---
    b.容器化构建
        a.功能说明
            使用Docker等容器技术可以简化CGO程序的编译。容器镜像中预装所有必需的编译器和依赖,确保构建环境一致性,避免"在我机器上能运行"的问题。
        b.代码示例
            ---
            // Dockerfile生成器
            package main

            import (
                "fmt"
                "os"
            )

            func main() {
                dockerfile := `# 多阶段构建Dockerfile示例
                # 第一阶段: 编译
                FROM golang:1.21-alpine AS builder

                # 安装编译依赖
                RUN apk add --no-cache gcc musl-dev sqlite-dev

                WORKDIR /app

                # 复制依赖文件
                COPY go.mod go.sum ./
                RUN go mod download

                # 复制源代码
                COPY . .

                # 编译应用(静态链接)
                RUN CGO_ENABLED=1 GOOS=linux go build -a \
                    -ldflags '-linkmode external -extldflags "-static"' \
                    -o /app/myapp .

                # 第二阶段: 运行
                FROM alpine:latest

                # 添加ca证书和时区数据
                RUN apk --no-cache add ca-certificates tzdata

                WORKDIR /root/

                # 从builder阶段复制编译好的程序
                COPY --from=builder /app/myapp .

                EXPOSE 8080

                CMD ["./myapp"]
                `

                fmt.Println("=== Docker构建配置 ===\n")
                fmt.Println("Dockerfile内容:")
                fmt.Println(dockerfile)

                // 写入Dockerfile
                err := os.WriteFile("Dockerfile.example", []byte(dockerfile), 0644)
                if err == nil {
                    fmt.Println("✓ Dockerfile已保存到 Dockerfile.example")
                }

                fmt.Println("\n构建命令:")
                fmt.Println("  docker build -t myapp:latest .")
                fmt.Println()

                fmt.Println("运行命令:")
                fmt.Println("  docker run -d -p 8080:8080 -v ./data:/data myapp:latest")
                fmt.Println()

                fmt.Println("优势:")
                fmt.Println("  ✓ 环境一致性")
                fmt.Println("  ✓ 无需本地安装C编译器")
                fmt.Println("  ✓ 支持多阶段构建减小镜像")
                fmt.Println("  ✓ 便于CI/CD集成")
            }
            ---

04.纯Go替代方案
    a.modernc-sqlite
        a.功能说明
            modernc.org/sqlite是纯Go实现的SQLite驱动,通过c2go工具将SQLite C代码转换为Go代码。无需CGO,支持跨平台编译,但性能略低于CGO版本约10-30%。
        b.代码示例
            ---
            // modernc-sqlite使用示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "runtime"
                "time"

                // 使用纯Go驱动
                _ "modernc.org/sqlite"
            )

            func main() {
                fmt.Println("=== modernc-sqlite 纯Go驱动 ===\n")

                // 连接数据库(驱动名为sqlite,不是sqlite3)
                db, err := sql.Open("sqlite", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 验证驱动信息
                var version string
                db.QueryRow("SELECT sqlite_version()").Scan(&version)
                fmt.Printf("SQLite版本: %s\n", version)
                fmt.Printf("驱动类型: 纯Go实现\n")
                fmt.Printf("CGO要求: 无\n")
                fmt.Printf("当前平台: %s/%s\n\n", runtime.GOOS, runtime.GOARCH)

                // 功能测试
                db.Exec(`CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)`)
                db.Exec(`INSERT INTO test (name) VALUES ('Alice'), ('Bob')`)

                rows, _ := db.Query(`SELECT id, name FROM test`)
                defer rows.Close()

                fmt.Println("数据查询:")
                for rows.Next() {
                    var id int
                    var name string
                    rows.Scan(&id, &name)
                    fmt.Printf("  %d: %s\n", id, name)
                }

                // 性能基准
                fmt.Println("\n性能测试:")
                start := time.Now()
                tx, _ := db.Begin()
                stmt, _ := tx.Prepare(`INSERT INTO test (name) VALUES (?)`)
                for i := 0; i < 10000; i++ {
                    stmt.Exec(fmt.Sprintf("User%d", i))
                }
                stmt.Close()
                tx.Commit()
                elapsed := time.Since(start)

                fmt.Printf("  插入10000条记录: %v\n", elapsed)
                fmt.Printf("  每秒操作数: %.0f ops/s\n", 10000/elapsed.Seconds())

                fmt.Println("\n优势:")
                fmt.Println("  ✓ 无需CGO,编译简单")
                fmt.Println("  ✓ 真正的跨平台编译")
                fmt.Println("  ✓ 容易调试(纯Go代码)")
                fmt.Println("  ✓ 无C编译器依赖")

                fmt.Println("\n劣势:")
                fmt.Println("  - 性能比CGO版本低10-30%")
                fmt.Println("  - 二进制文件略大")
                fmt.Println("  - 部分扩展可能不支持")
            }
            ---

1.7 驱动特性

01.连接池管理
    a.database/sql连接池
        a.功能说明
            Go的database/sql包内置连接池管理,通过SetMaxOpenConns、SetMaxIdleConns和SetConnMaxLifetime控制连接行为。对于SQLite,由于文件锁限制,通常设置MaxOpenConns为1以避免写入冲突。
        b.代码示例
            ---
            // SQLite连接池配置示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "sync"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                // 打开数据库连接
                db, err := sql.Open("sqlite3", "./pool_test.db")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // SQLite推荐配置
                // MaxOpenConns=1: 避免SQLITE_BUSY错误
                // 写操作是串行的,多个连接无益反而增加锁竞争
                db.SetMaxOpenConns(1)

                // MaxIdleConns=1: 保持一个空闲连接,减少打开关闭开销
                db.SetMaxIdleConns(1)

                // ConnMaxLifetime: 连接最大生存时间
                // SQLite文件数据库可以设置较长时间
                db.SetConnMaxLifetime(time.Hour)

                // ConnMaxIdleTime: 空闲连接最大生存时间
                db.SetConnMaxIdleTime(10 * time.Minute)

                fmt.Println("=== SQLite连接池配置 ===")
                fmt.Println("MaxOpenConns: 1 (推荐)")
                fmt.Println("MaxIdleConns: 1")
                fmt.Println("ConnMaxLifetime: 1小时")
                fmt.Println("ConnMaxIdleTime: 10分钟\n")

                // 创建测试表
                db.Exec(`CREATE TABLE IF NOT EXISTS metrics (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    value INTEGER,
                    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
                )`)

                // 并发写入测试
                var wg sync.WaitGroup
                start := time.Now()

                for i := 0; i < 10; i++ {
                    wg.Add(1)
                    go func(n int) {
                        defer wg.Done()
                        for j := 0; j < 100; j++ {
                            _, err := db.Exec(`INSERT INTO metrics (value) VALUES (?)`, n*100+j)
                            if err != nil {
                                log.Printf("插入失败: %v", err)
                            }
                        }
                    }(i)
                }

                wg.Wait()
                elapsed := time.Since(start)

                // 查看连接池统计
                stats := db.Stats()
                fmt.Println("连接池统计:")
                fmt.Printf("  MaxOpenConnections: %d\n", stats.MaxOpenConnections)
                fmt.Printf("  OpenConnections: %d\n", stats.OpenConnections)
                fmt.Printf("  InUse: %d\n", stats.InUse)
                fmt.Printf("  Idle: %d\n", stats.Idle)
                fmt.Printf("  WaitCount: %d (等待可用连接的次数)\n", stats.WaitCount)
                fmt.Printf("  WaitDuration: %v (总等待时间)\n", stats.WaitDuration)

                var count int
                db.QueryRow(`SELECT COUNT(*) FROM metrics`).Scan(&count)
                fmt.Printf("\n插入总数: %d, 耗时: %v\n", count, elapsed)
            }
            ---
    b.WAL模式下的连接
        a.功能说明
            在WAL模式下,可以适当增加连接数以利用读写并发。读操作可以并发执行,但写操作仍然是串行的。推荐配置MaxOpenConns为CPU核心数,MaxIdleConns为2-4。
        b.代码示例
            ---
            // WAL模式连接池优化
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "runtime"
                "sync"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func benchmarkConcurrency(maxOpen int, useWAL bool) time.Duration {
                mode := "DELETE"
                if useWAL {
                    mode = "WAL"
                }

                dsn := fmt.Sprintf(":memory:?_journal_mode=%s", mode)
                db, err := sql.Open("sqlite3", dsn)
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 配置连接池
                db.SetMaxOpenConns(maxOpen)
                db.SetMaxIdleConns(maxOpen / 2)

                // 初始化
                db.Exec(`CREATE TABLE test (id INTEGER PRIMARY KEY, data TEXT)`)
                for i := 0; i < 1000; i++ {
                    db.Exec(`INSERT INTO test (data) VALUES (?)`, fmt.Sprintf("data%d", i))
                }

                // 并发读写测试
                var wg sync.WaitGroup
                start := time.Now()

                // 1个写协程
                wg.Add(1)
                go func() {
                    defer wg.Done()
                    for i := 0; i < 500; i++ {
                        db.Exec(`UPDATE test SET data = ? WHERE id = ?`,
                            fmt.Sprintf("updated%d", i), i%100+1)
                    }
                }()

                // 多个读协程
                readers := maxOpen - 1
                if readers < 1 {
                    readers = 1
                }
                for i := 0; i < readers; i++ {
                    wg.Add(1)
                    go func() {
                        defer wg.Done()
                        for j := 0; j < 200; j++ {
                            var data string
                            db.QueryRow(`SELECT data FROM test WHERE id = ?`, j%100+1).Scan(&data)
                        }
                    }()
                }

                wg.Wait()
                return time.Since(start)
            }

            func main() {
                fmt.Println("=== WAL模式连接池性能测试 ===\n")
                cpuCount := runtime.NumCPU()
                fmt.Printf("CPU核心数: %d\n\n", cpuCount)

                // DELETE模式,单连接
                t1 := benchmarkConcurrency(1, false)
                fmt.Printf("DELETE模式 + MaxOpenConns=1: %v\n", t1)

                // DELETE模式,多连接(无效果)
                t2 := benchmarkConcurrency(cpuCount, false)
                fmt.Printf("DELETE模式 + MaxOpenConns=%d: %v\n", cpuCount, t2)

                // WAL模式,单连接
                t3 := benchmarkConcurrency(1, true)
                fmt.Printf("WAL模式 + MaxOpenConns=1: %v\n", t3)

                // WAL模式,多连接(有改善)
                t4 := benchmarkConcurrency(cpuCount, true)
                fmt.Printf("WAL模式 + MaxOpenConns=%d: %v\n", cpuCount, t4)

                fmt.Println("\n结论:")
                fmt.Println("  - DELETE模式: 使用MaxOpenConns=1")
                fmt.Println("  - WAL模式: 使用MaxOpenConns=CPU核心数")
                fmt.Println("  - WAL读写并发可提升性能")
            }
            ---

02.参数绑定
    a.位置参数
        a.功能说明
            SQLite支持?占位符表示位置参数,按顺序绑定。位置参数简洁高效,适合参数数量少且顺序固定的场景。database/sql会自动处理类型转换和SQL注入防护。
        b.代码示例
            ---
            // 位置参数绑定示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 创建测试表
                db.Exec(`CREATE TABLE products (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT NOT NULL,
                    price REAL NOT NULL,
                    stock INTEGER DEFAULT 0,
                    created_at DATETIME
                )`)

                fmt.Println("=== 位置参数绑定 ===\n")

                // 单个参数
                result, err := db.Exec(`INSERT INTO products (name, price, stock, created_at) VALUES (?, ?, ?, ?)`,
                    "笔记本电脑",
                    5999.00,
                    50,
                    time.Now(),
                )
                if err != nil {
                    log.Fatal(err)
                }

                id, _ := result.LastInsertId()
                fmt.Printf("插入产品ID: %d\n", id)

                // 批量插入
                tx, _ := db.Begin()
                stmt, _ := tx.Prepare(`INSERT INTO products (name, price, stock, created_at) VALUES (?, ?, ?, ?)`)

                products := []struct {
                    Name  string
                    Price float64
                    Stock int
                }{
                    {"手机", 3999.00, 100},
                    {"平板", 2999.00, 80},
                    {"耳机", 299.00, 200},
                }

                for _, p := range products {
                    stmt.Exec(p.Name, p.Price, p.Stock, time.Now())
                }
                stmt.Close()
                tx.Commit()

                fmt.Println("批量插入完成\n")

                // 查询参数绑定
                var name string
                var price float64
                err = db.QueryRow(`SELECT name, price FROM products WHERE id = ?`, 1).Scan(&name, &price)
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Printf("查询结果: %s, 价格: %.2f\n", name, price)

                // 多条件查询
                rows, _ := db.Query(`SELECT name, price FROM products WHERE price > ? AND stock > ?`, 1000.00, 50)
                defer rows.Close()

                fmt.Println("\n高价值库存商品:")
                for rows.Next() {
                    rows.Scan(&name, &price)
                    fmt.Printf("  - %s: ¥%.2f\n", name, price)
                }

                // 参数安全性演示
                fmt.Println("\nSQL注入防护:")
                maliciousInput := "'; DROP TABLE products; --"
                rows, _ = db.Query(`SELECT name FROM products WHERE name = ?`, maliciousInput)
                defer rows.Close()

                count := 0
                for rows.Next() {
                    count++
                }
                fmt.Printf("恶意输入查询结果: %d条 (参数绑定已防护)\n", count)

                // 验证表还在
                var tableExists int
                db.QueryRow(`SELECT COUNT(*) FROM products`).Scan(&tableExists)
                fmt.Printf("表仍然存在,记录数: %d\n", tableExists)
            }
            ---
    b.命名参数
        a.功能说明
            SQLite也支持:name、@name、$name等命名参数语法。命名参数可读性更好,参数顺序无关,适合复杂查询。go-sqlite3通过sql.Named函数支持命名参数。
        b.代码示例
            ---
            // 命名参数绑定示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                db.Exec(`CREATE TABLE users (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    username TEXT UNIQUE,
                    email TEXT,
                    age INTEGER,
                    active BOOLEAN
                )`)

                fmt.Println("=== 命名参数绑定 ===\n")

                // 使用:name语法
                _, err = db.Exec(`
                    INSERT INTO users (username, email, age, active)
                    VALUES (:username, :email, :age, :active)`,
                    sql.Named("username", "alice"),
                    sql.Named("email", "[email protected]"),
                    sql.Named("age", 25),
                    sql.Named("active", true),
                )
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Println("使用:name语法插入成功")

                // 使用@name语法
                _, err = db.Exec(`
                    INSERT INTO users (username, email, age, active)
                    VALUES (@username, @email, @age, @active)`,
                    sql.Named("username", "bob"),
                    sql.Named("email", "[email protected]"),
                    sql.Named("age", 30),
                    sql.Named("active", true),
                )
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Println("使用@name语法插入成功")

                // 使用$name语法
                _, err = db.Exec(`
                    INSERT INTO users (username, email, age, active)
                    VALUES ($username, $email, $age, $active)`,
                    sql.Named("username", "charlie"),
                    sql.Named("email", "[email protected]"),
                    sql.Named("age", 28),
                    sql.Named("active", false),
                )
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Println("使用$name语法插入成功\n")

                // 复杂查询使用命名参数
                rows, _ := db.Query(`
                    SELECT username, email, age
                    FROM users
                    WHERE age >= :min_age AND age <= :max_age AND active = :active
                    ORDER BY age`,
                    sql.Named("min_age", 20),
                    sql.Named("max_age", 30),
                    sql.Named("active", true),
                )
                defer rows.Close()

                fmt.Println("活跃用户(20-30岁):")
                for rows.Next() {
                    var username, email string
                    var age int
                    rows.Scan(&username, &email, &age)
                    fmt.Printf("  - %s (%d岁): %s\n", username, age, email)
                }

                // 更新使用命名参数
                result, _ := db.Exec(`
                    UPDATE users
                    SET email = :new_email, active = :active
                    WHERE username = :username`,
                    sql.Named("new_email", "[email protected]"),
                    sql.Named("active", false),
                    sql.Named("username", "alice"),
                )

                affected, _ := result.RowsAffected()
                fmt.Printf("\n更新影响行数: %d\n", affected)

                fmt.Println("\n命名参数优势:")
                fmt.Println("  ✓ 参数名称自描述")
                fmt.Println("  ✓ 顺序无关,易维护")
                fmt.Println("  ✓ 适合复杂查询")
            }
            ---

03.自定义函数
    a.标量函数
        a.功能说明
            go-sqlite3允许注册自定义SQL函数,扩展SQLite功能。标量函数接受输入参数返回单个值,可用于复杂计算、字符串处理、加密解密等场景。
        b.代码示例
            ---
            // 自定义标量函数示例
            package main

            import (
                "crypto/md5"
                "database/sql"
                "fmt"
                "log"
                "strings"

                "github.com/mattn/go-sqlite3"
            )

            func main() {
                // 注册自定义函数
                sql.Register("sqlite3_custom",
                    &sqlite3.SQLiteDriver{
                        ConnectHook: func(conn *sqlite3.SQLiteConn) error {
                            // MD5哈希函数
                            if err := conn.RegisterFunc("md5", func(s string) string {
                                return fmt.Sprintf("%x", md5.Sum([]byte(s)))
                            }, true); err != nil {
                                return err
                            }

                            // 字符串反转函数
                            if err := conn.RegisterFunc("reverse", func(s string) string {
                                runes := []rune(s)
                                for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
                                    runes[i], runes[j] = runes[j], runes[i]
                                }
                                return string(runes)
                            }, true); err != nil {
                                return err
                            }

                            // 大��转换函数
                            return conn.RegisterFunc("upper_cn", func(s string) string {
                                return strings.ToUpper(s)
                            }, true)
                        },
                    })

                // 使用自定义驱动打开数据库
                db, err := sql.Open("sqlite3_custom", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                fmt.Println("=== 自定义SQL函数 ===\n")

                // 测试MD5函数
                var hash string
                db.QueryRow(`SELECT md5(?)`, "Hello, SQLite!").Scan(&hash)
                fmt.Printf("MD5('Hello, SQLite!'): %s\n", hash)

                // 测试字符串反转
                var reversed string
                db.QueryRow(`SELECT reverse(?)`, "SQLite").Scan(&reversed)
                fmt.Printf("REVERSE('SQLite'): %s\n", reversed)

                // 测试大写函数
                var upper string
                db.QueryRow(`SELECT upper_cn(?)`, "你好世界").Scan(&upper)
                fmt.Printf("UPPER_CN('你好世界'): %s\n\n", upper)

                // 在实际查询中使用
                db.Exec(`CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, password TEXT)`)
                db.Exec(`INSERT INTO users (username, password) VALUES (?, md5(?))`, "alice", "secret123")

                db.QueryRow(`SELECT password FROM users WHERE username = ?`, "alice").Scan(&hash)
                fmt.Printf("用户密码哈希: %s\n", hash)

                // 验证密码
                var match bool
                db.QueryRow(`SELECT password = md5(?) FROM users WHERE username = ?`,
                    "secret123", "alice").Scan(&match)
                fmt.Printf("密码验证: %v\n", match)
            }
            ---
    b.聚合函数
        a.功能说明
            自定义聚合函数可以实现复杂的统计计算。聚合函数需要实现Step和Done方法,Step处理每一行数据,Done返回最终结果。适合实现自定义统计指标。
        b.代码示例
            ---
            // 自定义聚合函数示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "math"

                "github.com/mattn/go-sqlite3"
            )

            // StdDevAgg 标准差聚合函数
            type StdDevAgg struct {
                values []float64
            }

            func (s *StdDevAgg) Step(value float64) {
                s.values = append(s.values, value)
            }

            func (s *StdDevAgg) Done() float64 {
                if len(s.values) == 0 {
                    return 0
                }

                // 计算平均值
                var sum float64
                for _, v := range s.values {
                    sum += v
                }
                mean := sum / float64(len(s.values))

                // 计算方差
                var variance float64
                for _, v := range s.values {
                    variance += math.Pow(v-mean, 2)
                }
                variance /= float64(len(s.values))

                // 返回标准差
                return math.Sqrt(variance)
            }

            func main() {
                // 注册自定义聚合函数
                sql.Register("sqlite3_agg",
                    &sqlite3.SQLiteDriver{
                        ConnectHook: func(conn *sqlite3.SQLiteConn) error {
                            return conn.RegisterAggregator("stddev", func() *StdDevAgg {
                                return &StdDevAgg{}
                            }, true)
                        },
                    })

                db, err := sql.Open("sqlite3_agg", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                fmt.Println("=== 自定义聚合函数 ===\n")

                // 创建测试数据
                db.Exec(`CREATE TABLE scores (student TEXT, score REAL)`)
                scores := []float64{85, 90, 78, 92, 88, 76, 95, 82}
                for i, score := range scores {
                    db.Exec(`INSERT INTO scores VALUES (?, ?)`,
                        fmt.Sprintf("Student%d", i+1), score)
                }

                // 使用内置聚合函数
                var count int
                var avg, min, max float64
                db.QueryRow(`SELECT COUNT(*), AVG(score), MIN(score), MAX(score) FROM scores`).
                    Scan(&count, &avg, &min, &max)

                fmt.Printf("学生人数: %d\n", count)
                fmt.Printf("平均分: %.2f\n", avg)
                fmt.Printf("最低分: %.2f\n", min)
                fmt.Printf("最高分: %.2f\n", max)

                // 使用自定义标准差函数
                var stddev float64
                db.QueryRow(`SELECT stddev(score) FROM scores`).Scan(&stddev)
                fmt.Printf("标准差: %.2f\n\n", stddev)

                fmt.Println("成绩分布分析:")
                if stddev < 5 {
                    fmt.Println("  成绩分布集中")
                } else if stddev < 10 {
                    fmt.Println("  成绩分布正常")
                } else {
                    fmt.Println("  成绩分布离散")
                }
            }
            ---

2 数据库操作

2.1 汇总:6个核心操作

01.操作概览
    a.CRUD操作分类
        Go SQLite数据库操作遵循标准的CRUD模式,包括连接管理(Connection)、创建表(Create Table)、插入数据(Insert)、查询数据(Query)、更新数据(Update)和删除数据(Delete)六大核心操作。每种操作对应database/sql包的特定方法。
    b.方法映射关系
        ---
        // 核心操作方法映射表
        package main

        import (
            "database/sql"
            "fmt"
            "log"

            _ "github.com/mattn/go-sqlite3"
        )

        func main() {
            db, err := sql.Open("sqlite3", ":memory:")
            if err != nil {
                log.Fatal(err)
            }
            defer db.Close()

            fmt.Println("=== SQLite核心操作方法映射 ===\n")

            // 1. 连接管理
            fmt.Println("1. 连接管理:")
            fmt.Println("   sql.Open()        - 打开数据库连接")
            fmt.Println("   db.Ping()         - 验证连接有效性")
            fmt.Println("   db.Close()        - 关闭数据库连接")
            fmt.Println("   db.SetMaxOpenConns() - 设置最大连接数")

            // 2. DDL操作(Data Definition Language)
            fmt.Println("\n2. DDL操作(创建表):")
            fmt.Println("   db.Exec()         - 执行CREATE TABLE语句")
            fmt.Println("   db.Exec()         - 执行ALTER TABLE语句")
            fmt.Println("   db.Exec()         - 执行DROP TABLE语句")

            // 3. DML操作(Data Manipulation Language)
            fmt.Println("\n3. DML操作(数据操作):")
            fmt.Println("   db.Exec()         - INSERT插入数据")
            fmt.Println("   db.Query()        - SELECT查询多行")
            fmt.Println("   db.QueryRow()     - SELECT查询单行")
            fmt.Println("   db.Exec()         - UPDATE更新数据")
            fmt.Println("   db.Exec()         - DELETE删除数据")

            // 4. 事务操作
            fmt.Println("\n4. 事务操作:")
            fmt.Println("   db.Begin()        - 开始事务")
            fmt.Println("   tx.Commit()       - 提交事务")
            fmt.Println("   tx.Rollback()     - 回滚事务")

            // 5. 预编译语句
            fmt.Println("\n5. 预编译语句:")
            fmt.Println("   db.Prepare()      - 创建预编译语句")
            fmt.Println("   stmt.Exec()       - 执行预编译语句")
            fmt.Println("   stmt.Query()      - 查询预编译语句")
            fmt.Println("   stmt.Close()      - 关闭预编译语句")

            // 演示基本操作流程
            fmt.Println("\n=== 基本操作流程演示 ===\n")

            // 创建表
            _, err = db.Exec(`CREATE TABLE demo (id INTEGER PRIMARY KEY, name TEXT)`)
            if err != nil {
                log.Fatal(err)
            }
            fmt.Println("✓ 表创建成功")

            // 插入数据
            result, err := db.Exec(`INSERT INTO demo (name) VALUES (?)`, "示例数据")
            if err != nil {
                log.Fatal(err)
            }
            id, _ := result.LastInsertId()
            fmt.Printf("✓ 数据插入成功, ID: %d\n", id)

            // 查询数据
            var name string
            err = db.QueryRow(`SELECT name FROM demo WHERE id = ?`, id).Scan(&name)
            if err != nil {
                log.Fatal(err)
            }
            fmt.Printf("✓ 数据查询成功: %s\n", name)

            // 更新数据
            _, err = db.Exec(`UPDATE demo SET name = ? WHERE id = ?`, "更新后的数据", id)
            if err != nil {
                log.Fatal(err)
            }
            fmt.Println("✓ 数据更新成功")

            // 删除数据
            _, err = db.Exec(`DELETE FROM demo WHERE id = ?`, id)
            if err != nil {
                log.Fatal(err)
            }
            fmt.Println("✓ 数据删除成功")
        }
        ---

02.操作特点
    a.同步执行模型
        a.功能说明
            database/sql的所有操作都是同步阻塞的,调用方法会等待数据库操作完成后才返回。对于耗时操作,建议使用带Context的方法(如ExecContext、QueryContext)实现超时控制和取消功能。
        b.代码示例
            ---
            // 同步执行与超时控制示例
            package main

            import (
                "context"
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                db.Exec(`CREATE TABLE tasks (id INTEGER PRIMARY KEY, name TEXT)`)

                fmt.Println("=== 同步执行与超时控制 ===\n")

                // 普通同步执行
                start := time.Now()
                _, err = db.Exec(`INSERT INTO tasks (name) VALUES (?)`, "任务1")
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Printf("普通Exec耗时: %v\n", time.Since(start))

                // 使用Context的超时控制
                ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
                defer cancel()

                start = time.Now()
                _, err = db.ExecContext(ctx, `INSERT INTO tasks (name) VALUES (?)`, "任务2")
                if err != nil {
                    log.Printf("ExecContext失败: %v\n", err)
                } else {
                    fmt.Printf("ExecContext耗时: %v\n", time.Since(start))
                }

                // 查询超时示例
                queryCtx, queryCancel := context.WithTimeout(context.Background(), 1*time.Second)
                defer queryCancel()

                rows, err := db.QueryContext(queryCtx, `SELECT * FROM tasks`)
                if err != nil {
                    log.Printf("查询失败: %v\n", err)
                } else {
                    defer rows.Close()
                    count := 0
                    for rows.Next() {
                        count++
                    }
                    fmt.Printf("查询到 %d 条记录\n", count)
                }

                // 手动取消示例
                cancelCtx, manualCancel := context.WithCancel(context.Background())

                go func() {
                    time.Sleep(100 * time.Millisecond)
                    manualCancel() // 手动取消
                    fmt.Println("操作已手动取消")
                }()

                _, err = db.ExecContext(cancelCtx, `INSERT INTO tasks (name) VALUES (?)`, "任务3")
                if err != nil {
                    fmt.Printf("预期的取消错误: %v\n", err)
                }

                fmt.Println("\n超时控制建议:")
                fmt.Println("  - 用户交互操作: 1-5秒超时")
                fmt.Println("  - 后台任务: 30-60秒超时")
                fmt.Println("  - 批量处理: 根据数据量设置")
            }
            ---
    b.错误处理模式
        a.功能说明
            所有数据库操作都返回error类型,需要检查错误并妥善处理。常见错误包括连接失败、SQL语法错误、约束违反、记录不存在等。sql.ErrNoRows是查询无结果的特殊错误。
        b.代码示例
            ---
            // 错误处理最佳实践
            package main

            import (
                "database/sql"
                "errors"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal("打开数据库失败:", err)
                }
                defer db.Close()

                fmt.Println("=== 错误处理模式 ===\n")

                // 1. SQL语法错误
                _, err = db.Exec(`CREATE TABEL users (id INTEGER)`) // 故意拼错TABLE
                if err != nil {
                    fmt.Printf("SQL语法错误: %v\n", err)
                }

                // 正确创建表
                db.Exec(`CREATE TABLE users (
                    id INTEGER PRIMARY KEY,
                    username TEXT UNIQUE NOT NULL,
                    email TEXT
                )`)

                // 2. 约束违反错误
                db.Exec(`INSERT INTO users (username, email) VALUES ('alice', '[email protected]')`)
                _, err = db.Exec(`INSERT INTO users (username, email) VALUES ('alice', '[email protected]')`)
                if err != nil {
                    fmt.Printf("唯一性约束违反: %v\n", err)
                }

                // 3. NOT NULL约束错误
                _, err = db.Exec(`INSERT INTO users (email) VALUES ('[email protected]')`)
                if err != nil {
                    fmt.Printf("NOT NULL约束违反: %v\n", err)
                }

                // 4. sql.ErrNoRows处理
                var username string
                err = db.QueryRow(`SELECT username FROM users WHERE id = 999`).Scan(&username)
                if err != nil {
                    if errors.Is(err, sql.ErrNoRows) {
                        fmt.Println("记录不存在(这是正常情况)")
                    } else {
                        fmt.Printf("查询错误: %v\n", err)
                    }
                }

                // 5. 正确的查询处理
                err = db.QueryRow(`SELECT username FROM users WHERE id = 1`).Scan(&username)
                if err == nil {
                    fmt.Printf("查询成功: %s\n", username)
                } else if errors.Is(err, sql.ErrNoRows) {
                    fmt.Println("用户不存在")
                } else {
                    fmt.Printf("查询失败: %v\n", err)
                }

                // 6. 事务错误处理
                tx, err := db.Begin()
                if err != nil {
                    log.Fatal("开始事务失败:", err)
                }

                _, err = tx.Exec(`INSERT INTO users (username, email) VALUES ('bob', '[email protected]')`)
                if err != nil {
                    tx.Rollback()
                    fmt.Printf("插入失败,已回滚: %v\n", err)
                } else {
                    if err := tx.Commit(); err != nil {
                        fmt.Printf("提交失败: %v\n", err)
                    } else {
                        fmt.Println("事务提交成功")
                    }
                }

                fmt.Println("\n错误处理建议:")
                fmt.Println("  ✓ 始终检查err != nil")
                fmt.Println("  ✓ 区分sql.ErrNoRows和其他错误")
                fmt.Println("  ✓ 记录详细错误日志")
                fmt.Println("  ✓ 事务失败时及时回滚")
            }
            ---

03.性能考虑
    a.批量操作优化
        a.功能说明
            对于大量数据插入或更新,应使用事务批量处理而非逐条操作。事务可以将多个操作合并为一次磁盘写入,性能提升可达数百倍。预编译语句复用可以进一步提高性能。
        b.代码示例
            ---
            // 批量操作性能对比
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func benchmarkInsert(db *sql.DB, method string, count int) time.Duration {
                // 清空表
                db.Exec(`DELETE FROM benchmark`)

                start := time.Now()

                switch method {
                case "single":
                    // 方法1: 逐条插入(最慢)
                    for i := 0; i < count; i++ {
                        db.Exec(`INSERT INTO benchmark (value) VALUES (?)`, i)
                    }

                case "transaction":
                    // 方法2: 事务批量插入
                    tx, _ := db.Begin()
                    for i := 0; i < count; i++ {
                        tx.Exec(`INSERT INTO benchmark (value) VALUES (?)`, i)
                    }
                    tx.Commit()

                case "prepared":
                    // 方法3: 预编译语句+事务(最快)
                    tx, _ := db.Begin()
                    stmt, _ := tx.Prepare(`INSERT INTO benchmark (value) VALUES (?)`)
                    for i := 0; i < count; i++ {
                        stmt.Exec(i)
                    }
                    stmt.Close()
                    tx.Commit()
                }

                return time.Since(start)
            }

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                db.Exec(`CREATE TABLE benchmark (id INTEGER PRIMARY KEY, value INTEGER)`)

                fmt.Println("=== 批量操作性能对比 ===\n")
                count := 1000

                // 逐条插入
                t1 := benchmarkInsert(db, "single", count)
                fmt.Printf("逐条插入 %d 条: %v\n", count, t1)

                // 事务批量插入
                t2 := benchmarkInsert(db, "transaction", count)
                fmt.Printf("事务批量 %d 条: %v (提升 %.1fx)\n", count, t2, float64(t1)/float64(t2))

                // 预编译+事务
                t3 := benchmarkInsert(db, "prepared", count)
                fmt.Printf("预编译+事务 %d 条: %v (提升 %.1fx)\n", count, t3, float64(t1)/float64(t3))

                fmt.Println("\n性能优化建议:")
                fmt.Println("  1. 批量操作必须使用事务")
                fmt.Println("  2. 重复操作使用预编译语句")
                fmt.Println("  3. 合理设置事务大小(1000-10000条)")
                fmt.Println("  4. 关闭同步模式提升写入速度")

                // 验证数据
                var total int
                db.QueryRow(`SELECT COUNT(*) FROM benchmark`).Scan(&total)
                fmt.Printf("\n最终记录数: %d\n", total)
            }
            ---
    b.连接复用
        a.功能说明
            sql.DB对象内部维护连接池,应该全局创建一次并复用,而不是每次操作都打开关闭。频繁的Open/Close会带来巨大的性能开销,还可能导致文件句柄泄漏。
        b.代码示例
            ---
            // 连接复用最佳实践
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "sync"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            // 错误示例: 每次操作都打开关闭
            func badPractice() time.Duration {
                start := time.Now()
                for i := 0; i < 100; i++ {
                    db, _ := sql.Open("sqlite3", ":memory:")
                    db.Exec(`CREATE TABLE IF NOT EXISTS test (id INTEGER)`)
                    db.Exec(`INSERT INTO test VALUES (?)`, i)
                    db.Close()
                }
                return time.Since(start)
            }

            // 正确示例: 复用连接
            func goodPractice() time.Duration {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(`CREATE TABLE test (id INTEGER)`)

                start := time.Now()
                for i := 0; i < 100; i++ {
                    db.Exec(`INSERT INTO test VALUES (?)`, i)
                }
                return time.Since(start)
            }

            // 全局数据库实例(推荐模式)
            var globalDB *sql.DB
            var once sync.Once

            func GetDB() *sql.DB {
                once.Do(func() {
                    var err error
                    globalDB, err = sql.Open("sqlite3", "./app.db")
                    if err != nil {
                        log.Fatal(err)
                    }
                    globalDB.SetMaxOpenConns(1)
                    globalDB.SetMaxIdleConns(1)
                    globalDB.SetConnMaxLifetime(time.Hour)
                })
                return globalDB
            }

            func main() {
                fmt.Println("=== 连接复用性能对比 ===\n")

                // 对比测试
                badTime := badPractice()
                goodTime := goodPractice()

                fmt.Printf("频繁开关连接: %v\n", badTime)
                fmt.Printf("复用连接: %v\n", goodTime)
                fmt.Printf("性能提升: %.1fx\n", float64(badTime)/float64(goodTime))

                fmt.Println("\n推荐模式: 全局单例")
                fmt.Println("---")
                fmt.Println("var db *sql.DB")
                fmt.Println("")
                fmt.Println("func init() {")
                fmt.Println("    db, _ = sql.Open(\"sqlite3\", \"app.db\")")
                fmt.Println("    db.SetMaxOpenConns(1)")
                fmt.Println("}")
                fmt.Println("")
                fmt.Println("func main() {")
                fmt.Println("    defer db.Close()")
                fmt.Println("    // 使用db进行所有数据库操作")
                fmt.Println("}")
                fmt.Println("---")

                // 演示全局单例使用
                db := GetDB()
                defer db.Close()

                db.Exec(`CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)`)
                db.Exec(`INSERT INTO users (name) VALUES ('Alice')`)

                var count int
                db.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&count)
                fmt.Printf("\n使用全局DB实例查询: %d 条记录\n", count)
            }
            ---

2.2 连接管理

01.打开连接
    a.sql.Open方法
        a.功能说明
            sql.Open接受驱动名称和DSN连接字符串,返回*sql.DB对象。注意Open方法只是初始化连接池,并不会立即建立数据库连接,需要调用Ping方法验证连接是否可用。
        b.代码示例
            ---
            // sql.Open详解
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "os"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                fmt.Println("=== sql.Open方法详解 ===\n")

                // Open不会立即连接数据库
                fmt.Println("1. 调用sql.Open...")
                db, err := sql.Open("sqlite3", "./myapp.db")
                if err != nil {
                    log.Fatal("Open失败:", err)
                }
                defer db.Close()
                fmt.Println("   ✓ Open成功(但尚未建立连接)")

                // Ping才会真正建立连接
                fmt.Println("\n2. 调用db.Ping验证连接...")
                err = db.Ping()
                if err != nil {
                    log.Fatal("Ping失败:", err)
                }
                fmt.Println("   ✓ Ping成功(连接已建立)")

                // 检查数据库文件
                fileInfo, err := os.Stat("./myapp.db")
                if err == nil {
                    fmt.Printf("\n3. 数据库文件信息:\n")
                    fmt.Printf("   路径: %s\n", "./myapp.db")
                    fmt.Printf("   大小: %d bytes\n", fileInfo.Size())
                    fmt.Printf("   修改时间: %v\n", fileInfo.ModTime())
                }

                // 获取驱动信息
                fmt.Println("\n4. 驱动信息:")
                drivers := sql.Drivers()
                for _, driver := range drivers {
                    fmt.Printf("   - %s\n", driver)
                }

                // 执行简单查询验证
                var version string
                err = db.QueryRow("SELECT sqlite_version()").Scan(&version)
                if err != nil {
                    log.Fatal("查询失败:", err)
                }
                fmt.Printf("\n5. SQLite版本: %s\n", version)

                // 清理
                os.Remove("./myapp.db")
            }
            ---
    b.连接字符串选项
        a.功能说明
            SQLite的DSN支持丰富的选项配置,通过URL查询参数传递。常用选项包括缓存模式、日志模式、同步级别、忙等待超时等,合理配置可以显著影响性能和可靠性。
        b.代码示例
            ---
            // DSN连接选项最佳实践
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "net/url"

                _ "github.com/mattn/go-sqlite3"
            )

            func openWithOptions(name, dsn string) {
                db, err := sql.Open("sqlite3", dsn)
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 验证配置
                var journalMode, syncMode string
                var cacheSize, busyTimeout int

                db.QueryRow("PRAGMA journal_mode").Scan(&journalMode)
                db.QueryRow("PRAGMA synchronous").Scan(&syncMode)
                db.QueryRow("PRAGMA cache_size").Scan(&cacheSize)
                db.QueryRow("PRAGMA busy_timeout").Scan(&busyTimeout)

                fmt.Printf("%s配置:\n", name)
                fmt.Printf("  日志模式: %s\n", journalMode)
                fmt.Printf("  同步级别: %s\n", syncMode)
                fmt.Printf("  缓存大小: %d 页\n", cacheSize)
                fmt.Printf("  忙超时: %d ms\n\n", busyTimeout)
            }

            func main() {
                fmt.Println("=== DSN连接选项配置 ===\n")

                // 1. 默认配置
                openWithOptions("默认配置", ":memory:")

                // 2. 性能优化配置
                params := url.Values{}
                params.Set("_journal_mode", "WAL")      // WAL模式
                params.Set("_synchronous", "NORMAL")    // 平衡模式
                params.Set("_cache_size", "-64000")     // 64MB缓存
                params.Set("_busy_timeout", "5000")     // 5秒超时
                params.Set("_foreign_keys", "ON")       // 启用外键

                dsn := fmt.Sprintf("file::memory:?%s", params.Encode())
                openWithOptions("性能优化", dsn)

                // 3. 安全优先配置
                safeParams := url.Values{}
                safeParams.Set("_journal_mode", "DELETE")
                safeParams.Set("_synchronous", "FULL")
                safeParams.Set("_secure_delete", "ON")

                safeDSN := fmt.Sprintf("file::memory:?%s", safeParams.Encode())
                openWithOptions("安全优先", safeDSN)

                // 4. 只读模式
                readonlyParams := url.Values{}
                readonlyParams.Set("mode", "ro")
                readonlyDSN := fmt.Sprintf("file:readonly.db?%s", readonlyParams.Encode())

                fmt.Println("只读模式配置:")
                fmt.Printf("  DSN: %s\n", readonlyDSN)
                fmt.Println("  说明: 适用于数据分析、报表生成\n")

                // 5. 共享缓存模式
                sharedParams := url.Values{}
                sharedParams.Set("cache", "shared")
                sharedDSN := fmt.Sprintf("file::memory:?%s", sharedParams.Encode())

                fmt.Println("共享缓存配置:")
                fmt.Printf("  DSN: %s\n", sharedDSN)
                fmt.Println("  说明: 多连接共享内存数据库\n")

                fmt.Println("推荐配置场景:")
                fmt.Println("  桌面应用: WAL + NORMAL + 适中缓存")
                fmt.Println("  服务端: WAL + NORMAL + 大缓存 + 长超时")
                fmt.Println("  嵌入式: DELETE + NORMAL + 小缓存")
                fmt.Println("  临时数据: :memory: + 默认配置")
            }
            ---

02.连接验证
    a.Ping方法
        a.功能说明
            Ping方法向数据库发送一个简单的查询来验证连接是否有效。建议在应用启动时调用Ping确保数据库可访问,在长时间运行的程序中定期Ping检测连接健康状态。
        b.代码示例
            ---
            // 连接健康检查
            package main

            import (
                "context"
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            // HealthChecker 健康检查器
            type HealthChecker struct {
                db       *sql.DB
                interval time.Duration
                stopCh   chan struct{}
            }

            func NewHealthChecker(db *sql.DB, interval time.Duration) *HealthChecker {
                return &HealthChecker{
                    db:       db,
                    interval: interval,
                    stopCh:   make(chan struct{}),
                }
            }

            func (hc *HealthChecker) Start() {
                ticker := time.NewTicker(hc.interval)
                go func() {
                    for {
                        select {
                        case <-ticker.C:
                            hc.check()
                        case <-hc.stopCh:
                            ticker.Stop()
                            return
                        }
                    }
                }()
            }

            func (hc *HealthChecker) Stop() {
                close(hc.stopCh)
            }

            func (hc *HealthChecker) check() {
                ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
                defer cancel()

                start := time.Now()
                err := hc.db.PingContext(ctx)
                latency := time.Since(start)

                if err != nil {
                    log.Printf("❌ 健康检查失败: %v (延迟: %v)", err, latency)
                } else {
                    fmt.Printf("✓ 健康检查通过 (延迟: %v)\n", latency)
                }
            }

            func main() {
                fmt.Println("=== 数据库连接健康检查 ===\n")

                db, err := sql.Open("sqlite3", "./health_check.db")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 初始连接验证
                fmt.Println("1. 初始连接验证:")
                ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
                defer cancel()

                err = db.PingContext(ctx)
                if err != nil {
                    log.Fatal("   连接失败:", err)
                }
                fmt.Println("   ✓ 连接成功\n")

                // 获取连接统计
                stats := db.Stats()
                fmt.Println("2. 连接池状态:")
                fmt.Printf("   打开连接数: %d\n", stats.OpenConnections)
                fmt.Printf("   使用中: %d\n", stats.InUse)
                fmt.Printf("   空闲: %d\n\n", stats.Idle)

                // 启动定期健康检查
                fmt.Println("3. 启动定期健康检查(每2秒):")
                checker := NewHealthChecker(db, 2*time.Second)
                checker.Start()

                // 运行10秒
                time.Sleep(10 * time.Second)
                checker.Stop()

                fmt.Println("\n4. 最终连接统计:")
                finalStats := db.Stats()
                fmt.Printf("   总等待次数: %d\n", finalStats.WaitCount)
                fmt.Printf("   总等待时间: %v\n", finalStats.WaitDuration)
                fmt.Printf("   最大打开连接数: %d\n", finalStats.MaxOpenConnections)
            }
            ---

03.关闭连接
    a.Close方法
        a.功能说明
            Close方法关闭数据库连接池,释放所有资源。关闭后的db对象不能再使用。应该在应用退出时调用Close,通常使用defer确保正确关闭。对于临时数据库操作,使用defer db.Close()是最佳实践。
        b.代码示例
            ---
            // 连接关闭最佳实践
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "os"
                "os/signal"
                "syscall"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                fmt.Println("=== 连接关闭最佳实践 ===\n")

                // 1. 基本defer模式(推荐)
                fmt.Println("1. 基本defer模式:")
                func() {
                    db, err := sql.Open("sqlite3", ":memory:")
                    if err != nil {
                        log.Fatal(err)
                    }
                    defer db.Close() // 函数退出时自动关闭

                    db.Exec(`CREATE TABLE test (id INTEGER)`)
                    fmt.Println("   ✓ 使用defer确保关闭\n")
                }()

                // 2. 优雅关闭模式(长期运行服务)
                fmt.Println("2. 优雅关闭模式(捕获信号):")

                db, err := sql.Open("sqlite3", "./graceful.db")
                if err != nil {
                    log.Fatal(err)
                }

                // 捕获终止信号
                sigChan := make(chan os.Signal, 1)
                signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)

                // 模拟工作
                done := make(chan bool)
                go func() {
                    ticker := time.NewTicker(1 * time.Second)
                    defer ticker.Stop()

                    for {
                        select {
                        case <-ticker.C:
                            db.Exec(`CREATE TABLE IF NOT EXISTS heartbeat (ts INTEGER)`)
                            db.Exec(`INSERT INTO heartbeat VALUES (?)`, time.Now().Unix())
                        case <-done:
                            return
                        }
                    }
                }()

                // 等待信号或超时
                select {
                case sig := <-sigChan:
                    fmt.Printf("   收到信号: %v\n", sig)
                case <-time.After(3 * time.Second):
                    fmt.Println("   运行3秒后自动停止")
                }

                // 优雅关闭
                fmt.Println("   正在优雅关闭...")
                done <- true

                // 等待正在执行的查询完成
                time.Sleep(100 * time.Millisecond)

                // 获取最终统计
                stats := db.Stats()
                fmt.Printf("   最终打开连接数: %d\n", stats.OpenConnections)

                // 关闭数据库
                err = db.Close()
                if err != nil {
                    log.Printf("   关闭失败: %v\n", err)
                } else {
                    fmt.Println("   ✓ 数据库已关闭\n")
                }

                // 验证关闭后不能使用
                fmt.Println("3. 验证关闭后行为:")
                err = db.Ping()
                if err != nil {
                    fmt.Printf("   Ping失败(预期): %v\n", err)
                }

                _, err = db.Exec(`SELECT 1`)
                if err != nil {
                    fmt.Printf("   Exec失败(预期): %v\n\n", err)
                }

                // 4. 错误处理:重复关闭
                fmt.Println("4. 重复关闭测试:")
                err = db.Close()
                if err != nil {
                    fmt.Printf("   重复关闭错误: %v\n", err)
                } else {
                    fmt.Println("   重复关闭成功(无错误)")
                }

                fmt.Println("\n关闭建议:")
                fmt.Println("  - 短期操作: 使用defer db.Close()")
                fmt.Println("  - 长期服务: 捕获信号优雅关闭")
                fmt.Println("  - 连接池: 应用生命周期内保持打开")
                fmt.Println("  - 测试代码: defer确保资源清理")

                os.Remove("./graceful.db")
            }
            ---

04.连接池配置
    a.池参数设置
        a.功能说明
            database/sql通过SetMaxOpenConns、SetMaxIdleConns、SetConnMaxLifetime、SetConnMaxIdleTime四个方法配置连接池。对于SQLite,由于写入串行化,通常设置MaxOpenConns为1,避免锁竞争。
        b.代码示例
            ---
            // 连接池配置详解
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "sync"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func testPoolConfig(name string, maxOpen, maxIdle int, maxLifetime, maxIdleTime time.Duration) {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 配置连接池
                db.SetMaxOpenConns(maxOpen)
                db.SetMaxIdleConns(maxIdle)
                db.SetConnMaxLifetime(maxLifetime)
                db.SetConnMaxIdleTime(maxIdleTime)

                db.Exec(`CREATE TABLE test (id INTEGER PRIMARY KEY, value INTEGER)`)

                fmt.Printf("%s:\n", name)
                fmt.Printf("  MaxOpenConns: %d\n", maxOpen)
                fmt.Printf("  MaxIdleConns: %d\n", maxIdle)
                fmt.Printf("  ConnMaxLifetime: %v\n", maxLifetime)
                fmt.Printf("  ConnMaxIdleTime: %v\n", maxIdleTime)

                // 并发测试
                var wg sync.WaitGroup
                start := time.Now()

                for i := 0; i < 50; i++ {
                    wg.Add(1)
                    go func(n int) {
                        defer wg.Done()
                        db.Exec(`INSERT INTO test (value) VALUES (?)`, n)
                    }(i)
                }

                wg.Wait()
                elapsed := time.Since(start)

                stats := db.Stats()
                fmt.Printf("  性能: %v\n", elapsed)
                fmt.Printf("  等待次数: %d\n", stats.WaitCount)
                fmt.Printf("  等待时间: %v\n", stats.WaitDuration)
                fmt.Printf("  打开连接: %d\n\n", stats.OpenConnections)
            }

            func main() {
                fmt.Println("=== 连接池配置对比 ===\n")

                // 1. SQLite推荐配置
                testPoolConfig(
                    "SQLite推荐(单连接)",
                    1,                // MaxOpenConns
                    1,                // MaxIdleConns
                    time.Hour,        // ConnMaxLifetime
                    10*time.Minute,   // ConnMaxIdleTime
                )

                // 2. WAL模式配置
                testPoolConfig(
                    "WAL模式(多读一写)",
                    5,                // MaxOpenConns
                    2,                // MaxIdleConns
                    30*time.Minute,   // ConnMaxLifetime
                    5*time.Minute,    // ConnMaxIdleTime
                )

                // 3. 默认配置(不推荐)
                testPoolConfig(
                    "默认配置(无限制)",
                    0,                // 无限制
                    2,                // 默认2个空闲
                    0,                // 无限制
                    0,                // 无限制
                )

                // 详细说明
                fmt.Println("参数说明:")
                fmt.Println("  SetMaxOpenConns(n):")
                fmt.Println("    0: 无限制(不推荐)")
                fmt.Println("    1: SQLite DELETE模式推荐")
                fmt.Println("    CPU核心数: WAL模式推荐")
                fmt.Println()
                fmt.Println("  SetMaxIdleConns(n):")
                fmt.Println("    通常设为MaxOpenConns的1/2")
                fmt.Println("    太大: 浪费资源")
                fmt.Println("    太小: 频繁创建销毁连接")
                fmt.Println()
                fmt.Println("  SetConnMaxLifetime(d):")
                fmt.Println("    防止连接长期占用")
                fmt.Println("    文件数据库: 30分钟-1小时")
                fmt.Println("    内存数据库: 可设置较长")
                fmt.Println()
                fmt.Println("  SetConnMaxIdleTime(d):")
                fmt.Println("    空闲连接超时自动关闭")
                fmt.Println("    释放系统资源")
                fmt.Println("    通常5-10分钟")
            }
            ---

2.3 创建表

01.基本语法
    a.CREATE TABLE语句
        a.功能说明
            CREATE TABLE用于创建新表,定义列名、数据类型、约束和索引。SQLite的类型系统灵活,支持INTEGER、TEXT、REAL、BLOB、NUMERIC五种存储类。通过db.Exec执行DDL语句,不返回结果集。
        b.代码示例
            ---
            // CREATE TABLE基础示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                fmt.Println("=== CREATE TABLE基础 ===\n")

                // 1. 最简单的表
                _, err = db.Exec(`
                    CREATE TABLE simple (
                        id INTEGER,
                        name TEXT
                    )
                `)
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Println("1. 简单表创建成功")

                // 2. 完整类型示例
                _, err = db.Exec(`
                    CREATE TABLE types_demo (
                        id INTEGER,
                        name TEXT,
                        price REAL,
                        data BLOB,
                        quantity NUMERIC
                    )
                `)
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Println("2. 类型演示表创建成功")

                // 3. 带PRIMARY KEY的表
                _, err = db.Exec(`
                    CREATE TABLE users (
                        id INTEGER PRIMARY KEY,
                        username TEXT NOT NULL,
                        email TEXT,
                        created_at INTEGER
                    )
                `)
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Println("3. 用户表创建成功")

                // 4. AUTOINCREMENT主键
                _, err = db.Exec(`
                    CREATE TABLE posts (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        title TEXT NOT NULL,
                        content TEXT,
                        author_id INTEGER,
                        published_at DATETIME DEFAULT CURRENT_TIMESTAMP
                    )
                `)
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Println("4. 文章表(自增主键)创建成功")

                // 查询已创建的表
                fmt.Println("\n已创建的表:")
                rows, _ := db.Query(`
                    SELECT name, sql FROM sqlite_master
                    WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
                    ORDER BY name
                `)
                defer rows.Close()

                for rows.Next() {
                    var name, sql string
                    rows.Scan(&name, &sql)
                    fmt.Printf("\n表名: %s\n", name)
                    fmt.Printf("定义: %s\n", sql)
                }

                // 获取表结构
                fmt.Println("\n查看users表结构:")
                tableInfo, _ := db.Query(`PRAGMA table_info(users)`)
                defer tableInfo.Close()

                fmt.Println("列信息:")
                for tableInfo.Next() {
                    var cid int
                    var name, ctype string
                    var notnull, pk int
                    var dfltValue sql.NullString

                    tableInfo.Scan(&cid, &name, &ctype, &notnull, &dfltValue, &pk)
                    fmt.Printf("  %d: %s %s", cid, name, ctype)
                    if notnull == 1 {
                        fmt.Print(" NOT NULL")
                    }
                    if pk == 1 {
                        fmt.Print(" PRIMARY KEY")
                    }
                    fmt.Println()
                }
            }
            ---
    b.数据类型
        a.功能说明
            SQLite使用动态类型系统,列类型只是建议而非强制。数据实际存储为五种类型:NULL、INTEGER(整数)、REAL(浮点数)、TEXT(文本)、BLOB(二进制)。类型亲和性(Type Affinity)决定如何转换存储值。
        b.代码示例
            ---
            // SQLite数据类型详解
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                fmt.Println("=== SQLite数据类型系统 ===\n")

                // 创建演示表
                db.Exec(`
                    CREATE TABLE type_test (
                        int_col INTEGER,
                        text_col TEXT,
                        real_col REAL,
                        blob_col BLOB,
                        numeric_col NUMERIC,
                        any_col              -- 无类型声明
                    )
                `)

                // 插入不同类型数据
                db.Exec(`
                    INSERT INTO type_test VALUES (
                        42,                  -- INTEGER
                        'Hello SQLite',      -- TEXT
                        3.14159,             -- REAL
                        X'48656C6C6F',       -- BLOB (hex)
                        100.5,               -- NUMERIC
                        'anything'           -- ANY
                    )
                `)

                // 读取数据
                var intVal int64
                var textVal string
                var realVal float64
                var blobVal []byte
                var numericVal float64
                var anyVal interface{}

                err = db.QueryRow(`SELECT * FROM type_test`).Scan(
                    &intVal, &textVal, &realVal, &blobVal, &numericVal, &anyVal)
                if err != nil {
                    log.Fatal(err)
                }

                fmt.Println("1. 基本类型存储:")
                fmt.Printf("   INTEGER: %d (Go类型: %T)\n", intVal, intVal)
                fmt.Printf("   TEXT: %s (Go类型: %T)\n", textVal, textVal)
                fmt.Printf("   REAL: %.5f (Go类型: %T)\n", realVal, realVal)
                fmt.Printf("   BLOB: %v (Go类型: %T)\n", blobVal, blobVal)
                fmt.Printf("   NUMERIC: %.1f (Go类型: %T)\n", numericVal, numericVal)
                fmt.Printf("   ANY: %v (Go类型: %T)\n\n", anyVal, anyVal)

                // 类型亲和性测试
                db.Exec(`CREATE TABLE affinity_test (
                    varchar_col VARCHAR(50),
                    int_col INT,
                    double_col DOUBLE,
                    datetime_col DATETIME
                )`)

                db.Exec(`INSERT INTO affinity_test VALUES (?, ?, ?, ?)`,
                    "text value", 123, 45.67, time.Now().Unix())

                fmt.Println("2. 类型亲和性规则:")
                fmt.Println("   VARCHAR -> TEXT affinity")
                fmt.Println("   INT -> INTEGER affinity")
                fmt.Println("   DOUBLE -> REAL affinity")
                fmt.Println("   DATETIME -> NUMERIC affinity")

                // 动态类型演示
                db.Exec(`CREATE TABLE dynamic (value)`)
                db.Exec(`INSERT INTO dynamic VALUES (42)`)           // 整数
                db.Exec(`INSERT INTO dynamic VALUES (3.14)`)         // 浮点数
                db.Exec(`INSERT INTO dynamic VALUES ('text')`)       // 文本
                db.Exec(`INSERT INTO dynamic VALUES (NULL)`)         // NULL

                fmt.Println("\n3. 动态类型存储(同一列不同类型):")
                rows, _ := db.Query(`SELECT value, typeof(value) FROM dynamic`)
                defer rows.Close()

                for rows.Next() {
                    var value interface{}
                    var valueType string
                    rows.Scan(&value, &valueType)
                    fmt.Printf("   值: %v, SQLite类型: %s, Go类型: %T\n",
                        value, valueType, value)
                }

                // 布尔值处理
                db.Exec(`CREATE TABLE bool_test (active INTEGER)`)
                db.Exec(`INSERT INTO bool_test VALUES (1)`)  // true
                db.Exec(`INSERT INTO bool_test VALUES (0)`)  // false

                fmt.Println("\n4. 布尔值处理(SQLite无BOOLEAN类型):")
                boolRows, _ := db.Query(`SELECT active FROM bool_test`)
                defer boolRows.Close()

                for boolRows.Next() {
                    var active bool
                    boolRows.Scan(&active)
                    fmt.Printf("   布尔值: %v\n", active)
                }

                // 日期时间处理
                fmt.Println("\n5. 日期时间处理:")
                db.Exec(`CREATE TABLE events (
                    id INTEGER PRIMARY KEY,
                    created_at INTEGER,      -- Unix时间戳
                    updated_at TEXT,         -- ISO8601字符串
                    scheduled_at REAL        -- Julian Day Number
                )`)

                now := time.Now()
                db.Exec(`INSERT INTO events (created_at, updated_at, scheduled_at) VALUES (?, ?, ?)`,
                    now.Unix(),
                    now.Format(time.RFC3339),
                    float64(now.Unix())/86400.0 + 2440587.5,
                )

                var timestamp int64
                var isoString string
                var julianDay float64

                db.QueryRow(`SELECT created_at, updated_at, scheduled_at FROM events WHERE id = 1`).
                    Scan(&timestamp, &isoString, &julianDay)

                fmt.Printf("   Unix时间戳: %d\n", timestamp)
                fmt.Printf("   ISO8601: %s\n", isoString)
                fmt.Printf("   Julian Day: %.5f\n", julianDay)
            }
            ---

02.约束定义
    a.PRIMARY KEY约束
        a.功能说明
            PRIMARY KEY定义主键,确保唯一性且非空。INTEGER PRIMARY KEY是SQLite的特殊情况,会使用内置的ROWID作为主键,性能最优。AUTOINCREMENT确保ID永不重用,但会有轻微性能损失。
        b.代码示例
            ---
            // PRIMARY KEY约束详解
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                fmt.Println("=== PRIMARY KEY约束 ===\n")

                // 1. INTEGER PRIMARY KEY(使用ROWID)
                db.Exec(`
                    CREATE TABLE users (
                        id INTEGER PRIMARY KEY,
                        name TEXT
                    )
                `)

                // 插入数据(不指定ID,自动分配ROWID)
                result, _ := db.Exec(`INSERT INTO users (name) VALUES ('Alice')`)
                id1, _ := result.LastInsertId()
                fmt.Printf("1. INTEGER PRIMARY KEY (ROWID别名)\n")
                fmt.Printf("   自动分配ID: %d\n", id1)

                // 显式指定ID
                db.Exec(`INSERT INTO users (id, name) VALUES (100, 'Bob')`)
                fmt.Println("   显式指定ID: 100")

                // 再次插入不指定ID,会从101开始
                result, _ = db.Exec(`INSERT INTO users (name) VALUES ('Charlie')`)
                id2, _ := result.LastInsertId()
                fmt.Printf("   下一个自动ID: %d\n\n", id2)

                // 2. AUTOINCREMENT
                db.Exec(`
                    CREATE TABLE products (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        name TEXT
                    )
                `)

                db.Exec(`INSERT INTO products (name) VALUES ('Product A')`)
                db.Exec(`INSERT INTO products (name) VALUES ('Product B')`)
                result, _ = db.Exec(`INSERT INTO products (name) VALUES ('Product C')`)
                lastID, _ := result.LastInsertId()

                fmt.Printf("2. AUTOINCREMENT主键\n")
                fmt.Printf("   最后插入ID: %d\n", lastID)

                // 删除中间记录
                db.Exec(`DELETE FROM products WHERE id = 2`)

                // 再次插入,ID不会重用2
                result, _ = db.Exec(`INSERT INTO products (name) VALUES ('Product D')`)
                newID, _ := result.LastInsertId()
                fmt.Printf("   删除ID=2后,新ID: %d (不重用)\n\n", newID)

                // 3. 复合主键
                db.Exec(`
                    CREATE TABLE order_items (
                        order_id INTEGER,
                        product_id INTEGER,
                        quantity INTEGER,
                        PRIMARY KEY (order_id, product_id)
                    )
                `)

                db.Exec(`INSERT INTO order_items VALUES (1, 101, 2)`)
                db.Exec(`INSERT INTO order_items VALUES (1, 102, 1)`)
                db.Exec(`INSERT INTO order_items VALUES (2, 101, 3)`)

                fmt.Println("3. 复合主键:")
                rows, _ := db.Query(`SELECT * FROM order_items`)
                defer rows.Close()

                for rows.Next() {
                    var orderID, productID, quantity int
                    rows.Scan(&orderID, &productID, &quantity)
                    fmt.Printf("   订单%d, 产品%d, 数量%d\n", orderID, productID, quantity)
                }

                // 尝试插入重复主键
                _, err = db.Exec(`INSERT INTO order_items VALUES (1, 101, 5)`)
                if err != nil {
                    fmt.Printf("\n   重复主键错误: %v\n", err)
                }

                // 4. 非INTEGER主键
                db.Exec(`
                    CREATE TABLE sessions (
                        session_id TEXT PRIMARY KEY,
                        user_id INTEGER,
                        created_at INTEGER
                    )
                `)

                db.Exec(`INSERT INTO sessions VALUES ('sess_abc123', 1, ?)`, 1234567890)

                fmt.Println("\n4. 文本主键:")
                var sessionID string
                db.QueryRow(`SELECT session_id FROM sessions WHERE user_id = 1`).Scan(&sessionID)
                fmt.Printf("   会话ID: %s\n", sessionID)

                fmt.Println("\nPRIMARY KEY对比:")
                fmt.Println("  INTEGER PRIMARY KEY:")
                fmt.Println("    - 使用内置ROWID,性能最佳")
                fmt.Println("    - ID可能重用(删除后)")
                fmt.Println("    - 推荐用于大多数场景")
                fmt.Println("  INTEGER PRIMARY KEY AUTOINCREMENT:")
                fmt.Println("    - ID永不重用")
                fmt.Println("    - 额外维护sqlite_sequence表")
                fmt.Println("    - 适用于ID敏感场景")
            }
            ---
    b.其他约束
        a.功能说明
            SQLite支持NOT NULL、UNIQUE、CHECK、DEFAULT、FOREIGN KEY等约束。约束在插入和更新时自动检查,违反约束会导致操作失败并返回错误。
        b.代码示例
            ---
            // 数据库约束完整示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                // 启用外键约束
                db, err := sql.Open("sqlite3", ":memory:?_foreign_keys=ON")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                fmt.Println("=== 数据库约束详解 ===\n")

                // 创建带完整约束的表
                db.Exec(`
                    CREATE TABLE employees (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        username TEXT NOT NULL UNIQUE,
                        email TEXT NOT NULL UNIQUE,
                        age INTEGER CHECK (age >= 18 AND age <= 65),
                        salary REAL CHECK (salary > 0),
                        department TEXT DEFAULT 'General',
                        active INTEGER DEFAULT 1,
                        hired_date TEXT DEFAULT CURRENT_DATE
                    )
                `)

                fmt.Println("1. NOT NULL约束:")
                _, err = db.Exec(`INSERT INTO employees (age) VALUES (25)`)
                if err != nil {
                    fmt.Printf("   ✗ 缺少必填字段: %v\n\n", err)
                }

                fmt.Println("2. UNIQUE约束:")
                db.Exec(`INSERT INTO employees (username, email, age) VALUES ('alice', '[email protected]', 30)`)
                _, err = db.Exec(`INSERT INTO employees (username, email, age) VALUES ('alice', '[email protected]', 28)`)
                if err != nil {
                    fmt.Printf("   ✗ 用户名重复: %v\n\n", err)
                }

                fmt.Println("3. CHECK约束:")
                _, err = db.Exec(`INSERT INTO employees (username, email, age) VALUES ('bob', '[email protected]', 16)`)
                if err != nil {
                    fmt.Printf("   ✗ 年龄不符合要求: %v\n", err)
                }

                _, err = db.Exec(`INSERT INTO employees (username, email, age, salary) VALUES ('charlie', '[email protected]', 25, -1000)`)
                if err != nil {
                    fmt.Printf("   ✗ 薪水必须为正: %v\n\n", err)
                }

                fmt.Println("4. DEFAULT约束:")
                db.Exec(`INSERT INTO employees (username, email, age) VALUES ('david', '[email protected]', 28)`)

                var department string
                var active int
                var hiredDate string
                db.QueryRow(`SELECT department, active, hired_date FROM employees WHERE username = 'david'`).
                    Scan(&department, &active, &hiredDate)

                fmt.Printf("   默认部门: %s\n", department)
                fmt.Printf("   默认状态: %d\n", active)
                fmt.Printf("   默认入职日期: %s\n\n", hiredDate)

                // 5. FOREIGN KEY约束
                db.Exec(`
                    CREATE TABLE departments (
                        id INTEGER PRIMARY KEY,
                        name TEXT NOT NULL UNIQUE
                    )
                `)

                db.Exec(`
                    CREATE TABLE employees_fk (
                        id INTEGER PRIMARY KEY,
                        name TEXT NOT NULL,
                        dept_id INTEGER,
                        FOREIGN KEY (dept_id) REFERENCES departments(id)
                            ON DELETE CASCADE
                            ON UPDATE CASCADE
                    )
                `)

                db.Exec(`INSERT INTO departments VALUES (1, 'Engineering')`)
                db.Exec(`INSERT INTO departments VALUES (2, 'Sales')`)

                fmt.Println("5. FOREIGN KEY约束:")
                db.Exec(`INSERT INTO employees_fk VALUES (1, 'Alice', 1)`)
                fmt.Println("   ✓ 引用有效部门成功")

                _, err = db.Exec(`INSERT INTO employees_fk VALUES (2, 'Bob', 999)`)
                if err != nil {
                    fmt.Printf("   ✗ 引用无效部门: %v\n", err)
                }

                // 级联删除测试
                db.Exec(`DELETE FROM departments WHERE id = 1`)
                var count int
                db.QueryRow(`SELECT COUNT(*) FROM employees_fk WHERE dept_id = 1`).Scan(&count)
                fmt.Printf("   级联删除后员工数: %d\n", count)

                fmt.Println("\n约束类型总结:")
                fmt.Println("  NOT NULL: 列不能为空")
                fmt.Println("  UNIQUE: 列值必须唯一")
                fmt.Println("  PRIMARY KEY: 唯一标识记录")
                fmt.Println("  FOREIGN KEY: 引用完整性")
                fmt.Println("  CHECK: 自定义验证规则")
                fmt.Println("  DEFAULT: 默认值")
            }
            ---

03.条件创建
    a.IF NOT EXISTS
        a.功能说明
            IF NOT EXISTS子句使CREATE TABLE语句在表已存在时不报错,而是静默跳过。这对于应用初始化脚本和迁移脚本非常有用,可以安全地重复执行而不会失败。
        b.代码示例
            ---
            // 条件创建表实践
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            // InitDatabase 数据库初始化函数(幂等性)
            func InitDatabase(db *sql.DB) error {
                // 用户表
                _, err := db.Exec(`
                    CREATE TABLE IF NOT EXISTS users (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        username TEXT NOT NULL UNIQUE,
                        password_hash TEXT NOT NULL,
                        created_at INTEGER DEFAULT (strftime('%s', 'now'))
                    )
                `)
                if err != nil {
                    return fmt.Errorf("创建users表失败: %w", err)
                }

                // 配置表
                _, err = db.Exec(`
                    CREATE TABLE IF NOT EXISTS settings (
                        key TEXT PRIMARY KEY,
                        value TEXT,
                        updated_at INTEGER DEFAULT (strftime('%s', 'now'))
                    )
                `)
                if err != nil {
                    return fmt.Errorf("创建settings表失败: %w", err)
                }

                // 日志表
                _, err = db.Exec(`
                    CREATE TABLE IF NOT EXISTS logs (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        level TEXT,
                        message TEXT,
                        timestamp INTEGER DEFAULT (strftime('%s', 'now'))
                    )
                `)
                if err != nil {
                    return fmt.Errorf("创建logs表失败: %w", err)
                }

                return nil
            }

            func main() {
                db, err := sql.Open("sqlite3", "./app.db")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                fmt.Println("=== IF NOT EXISTS使用 ===\n")

                // 第一次初始化
                fmt.Println("第一次初始化:")
                err = InitDatabase(db)
                if err != nil {
                    log.Fatal(err)
                }

                // 查询创建的表
                var tableCount int
                db.QueryRow(`
                    SELECT COUNT(*) FROM sqlite_master
                    WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
                `).Scan(&tableCount)
                fmt.Printf("  创建了 %d 个表\n\n", tableCount)

                // 第二次初始化(幂等性)
                fmt.Println("第二次初始化(重复执行):")
                err = InitDatabase(db)
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Println("  ✓ 没有报错,幂等性保证\n")

                // 检查表是否存在的函数
                tableExists := func(tableName string) bool {
                    var exists int
                    db.QueryRow(`
                        SELECT COUNT(*) FROM sqlite_master
                        WHERE type = 'table' AND name = ?
                    `, tableName).Scan(&exists)
                    return exists > 0
                }

                fmt.Println("验证表存在性:")
                tables := []string{"users", "settings", "logs", "nonexistent"}
                for _, table := range tables {
                    if tableExists(table) {
                        fmt.Printf("  ✓ %s 表存在\n", table)
                    } else {
                        fmt.Printf("  ✗ %s 表不存在\n", table)
                    }
                }

                // 插入测试数据
                db.Exec(`INSERT INTO users (username, password_hash) VALUES ('admin', 'hash123')`)
                db.Exec(`INSERT INTO settings VALUES ('app_version', '1.0.0', NULL)`)
                db.Exec(`INSERT INTO logs (level, message) VALUES ('INFO', '应用启动')`)

                // 第三次初始化,验证数据未丢失
                fmt.Println("\n第三次初始化:")
                err = InitDatabase(db)
                if err != nil {
                    log.Fatal(err)
                }

                var userCount, settingCount, logCount int
                db.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&userCount)
                db.QueryRow(`SELECT COUNT(*) FROM settings`).Scan(&settingCount)
                db.QueryRow(`SELECT COUNT(*) FROM logs`).Scan(&logCount)

                fmt.Printf("  用户数: %d\n", userCount)
                fmt.Printf("  配置数: %d\n", settingCount)
                fmt.Printf("  日志数: %d\n", logCount)
                fmt.Println("  ✓ 数据未丢失")

                fmt.Println("\n最佳实践:")
                fmt.Println("  1. 应用启动时调用初始化函数")
                fmt.Println("  2. 使用IF NOT EXISTS确保幂等性")
                fmt.Println("  3. 集中管理表结构定义")
                fmt.Println("  4. 错误处理返回详细信息")
            }
            ---

2.4 插入数据

01.基本插入
    a.INSERT语句
        a.功能说明
            INSERT INTO语句用于向表中插入新记录。可以插入完整行或指定列,支持VALUES子句提供字面值或使用参数绑定。db.Exec方法执行插入,返回Result对象包含LastInsertId和RowsAffected信息。
        b.代码示例
            ---
            // INSERT基础操作
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                // 创建测试表
                db.Exec(`
                    CREATE TABLE products (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        name TEXT NOT NULL,
                        price REAL NOT NULL,
                        stock INTEGER DEFAULT 0,
                        created_at INTEGER
                    )
                `)

                fmt.Println("=== INSERT基础操作 ===\n")

                // 1. 插入所有列
                result, err := db.Exec(`
                    INSERT INTO products (name, price, stock, created_at)
                    VALUES ('笔记本', 5999.00, 50, ?)
                `, time.Now().Unix())

                if err != nil {
                    log.Fatal(err)
                }

                id, _ := result.LastInsertId()
                affected, _ := result.RowsAffected()
                fmt.Printf("1. 插入所有列:\n")
                fmt.Printf("   新记录ID: %d\n", id)
                fmt.Printf("   影响行数: %d\n\n", affected)

                // 2. 插入部分列(使用DEFAULT)
                result, _ = db.Exec(`
                    INSERT INTO products (name, price)
                    VALUES ('手机', 3999.00)
                `)

                id, _ = result.LastInsertId()
                fmt.Printf("2. 插入部分列(stock使用默认值0):\n")
                fmt.Printf("   新记录ID: %d\n\n", id)

                // 3. 使用参数绑定
                name := "平板"
                price := 2999.00
                stock := 30

                result, _ = db.Exec(`
                    INSERT INTO products (name, price, stock, created_at)
                    VALUES (?, ?, ?, ?)
                `, name, price, stock, time.Now().Unix())

                id, _ = result.LastInsertId()
                fmt.Printf("3. 参数绑定插入:\n")
                fmt.Printf("   产品: %s\n", name)
                fmt.Printf("   价格: %.2f\n", price)
                fmt.Printf("   新ID: %d\n\n", id)

                // 4. 插入并返回数据
                insertResult, _ := db.Exec(`
                    INSERT INTO products (name, price, stock)
                    VALUES ('耳机', 299.00, 100)
                `)

                lastID, _ := insertResult.LastInsertId()

                var insertedName string
                var insertedPrice float64
                db.QueryRow(`SELECT name, price FROM products WHERE id = ?`, lastID).
                    Scan(&insertedName, &insertedPrice)

                fmt.Printf("4. 插入后查询验证:\n")
                fmt.Printf("   ID: %d\n", lastID)
                fmt.Printf("   名称: %s\n", insertedName)
                fmt.Printf("   价格: %.2f\n\n", insertedPrice)

                // 5. 查看所有数据
                rows, _ := db.Query(`SELECT id, name, price, stock FROM products ORDER BY id`)
                defer rows.Close()

                fmt.Println("5. 所有产品:")
                for rows.Next() {
                    var id int
                    var name string
                    var price float64
                    var stock int
                    rows.Scan(&id, &name, &price, &stock)
                    fmt.Printf("   [%d] %s - ¥%.2f (库存:%d)\n", id, name, price, stock)
                }
            }
            ---
    b.返回值处理
        a.功能说明
            Exec返回sql.Result接口,提供LastInsertId获取自增ID和RowsAffected获取影响行数。LastInsertId对于INTEGER PRIMARY KEY返回ROWID,对于非自增主键可能不可用。错误处理检查约束违反等问题。
        b.代码示例
            ---
            // Result对象详解
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                db.Exec(`
                    CREATE TABLE users (
                        id INTEGER PRIMARY KEY AUTOINCREMENT,
                        username TEXT UNIQUE NOT NULL,
                        email TEXT
                    )
                `)

                fmt.Println("=== sql.Result详解 ===\n")

                // 1. 正常插入
                result, err := db.Exec(`
                    INSERT INTO users (username, email) VALUES (?, ?)
                `, "alice", "[email protected]")

                if err != nil {
                    log.Fatal(err)
                }

                lastID, err := result.LastInsertId()
                if err != nil {
                    fmt.Printf("LastInsertId错误: %v\n", err)
                } else {
                    fmt.Printf("1. LastInsertId: %d\n", lastID)
                }

                rowsAffected, err := result.RowsAffected()
                if err != nil {
                    fmt.Printf("RowsAffected错误: %v\n", err)
                } else {
                    fmt.Printf("   RowsAffected: %d\n\n", rowsAffected)
                }

                // 2. 插入多条(循环)
                fmt.Println("2. 批量插入:")
                var totalAffected int64
                users := []struct {
                    Username string
                    Email    string
                }{
                    {"bob", "[email protected]"},
                    {"charlie", "[email protected]"},
                    {"david", "[email protected]"},
                }

                for _, u := range users {
                    result, err := db.Exec(`INSERT INTO users (username, email) VALUES (?, ?)`,
                        u.Username, u.Email)
                    if err != nil {
                        log.Printf("   插入%s失败: %v\n", u.Username, err)
                        continue
                    }
                    affected, _ := result.RowsAffected()
                    totalAffected += affected
                }
                fmt.Printf("   总共影响: %d 行\n\n", totalAffected)

                // 3. 约束违反处理
                fmt.Println("3. 约束违反:")
                result, err = db.Exec(`INSERT INTO users (username, email) VALUES (?, ?)`,
                    "alice", "[email protected]")

                if err != nil {
                    fmt.Printf("   ✗ 插入失败: %v\n", err)
                    fmt.Println("   (用户名已存在)")
                } else {
                    affected, _ := result.RowsAffected()
                    fmt.Printf("   影响行数: %d\n", affected)
                }

                // 4. 验证数据
                var count int
                db.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&count)
                fmt.Printf("\n4. 最终用户数: %d\n", count)

                fmt.Println("\n最佳实践:")
                fmt.Println("  ✓ 始终检查错误")
                fmt.Println("  ✓ 使用LastInsertId获取新ID")
                fmt.Println("  ✓ 使用RowsAffected确认影响")
                fmt.Println("  ✓ 约束违反时妥善处理")
            }
            ---

02.批量插入
    a.事务批量
        a.功能说明
            批量插入大量数据时,必须使用事务将多个INSERT合并为一次提交,否则每次INSERT都会触发磁盘同步,性能极差。事务将所有操作缓存在内存,commit时一次性写入,性能提升可达数百倍。
        b.代码示例
            ---
            // 批量插入性能优化
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func insertWithoutTransaction(db *sql.DB, count int) time.Duration {
                db.Exec(`DELETE FROM benchmark`)

                start := time.Now()
                for i := 0; i < count; i++ {
                    db.Exec(`INSERT INTO benchmark (value) VALUES (?)`, i)
                }
                return time.Since(start)
            }

            func insertWithTransaction(db *sql.DB, count int) time.Duration {
                db.Exec(`DELETE FROM benchmark`)

                start := time.Now()

                tx, _ := db.Begin()
                for i := 0; i < count; i++ {
                    tx.Exec(`INSERT INTO benchmark (value) VALUES (?)`, i)
                }
                tx.Commit()

                return time.Since(start)
            }

            func insertWithPrepared(db *sql.DB, count int) time.Duration {
                db.Exec(`DELETE FROM benchmark`)

                start := time.Now()

                tx, _ := db.Begin()
                stmt, _ := tx.Prepare(`INSERT INTO benchmark (value) VALUES (?)`)
                defer stmt.Close()

                for i := 0; i < count; i++ {
                    stmt.Exec(i)
                }
                tx.Commit()

                return time.Since(start)
            }

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                db.Exec(`CREATE TABLE benchmark (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    value INTEGER
                )`)

                fmt.Println("=== 批量插入性能对比 ===\n")

                count := 10000
                fmt.Printf("插入 %d 条记录:\n\n", count)

                // 方法1: 无事务(很慢,不推荐)
                if count <= 1000 { // 仅小数据量测试
                    t1 := insertWithoutTransaction(db, count)
                    fmt.Printf("1. 无事务: %v\n", t1)
                }

                // 方法2: 使用事务
                t2 := insertWithTransaction(db, count)
                fmt.Printf("2. 使用事务: %v\n", t2)

                // 方法3: 预编译+事务
                t3 := insertWithPrepared(db, count)
                fmt.Printf("3. 预编译+事务: %v\n", t3)

                improvement := float64(t2) / float64(t3)
                fmt.Printf("\n预编译提升: %.2fx\n", improvement)

                // 大批量测试
                fmt.Println("\n=== 大批量插入测试 ===\n")

                largeCount := 100000
                fmt.Printf("插入 %d 条记录:\n", largeCount)

                start := time.Now()
                tx, _ := db.Begin()
                stmt, _ := tx.Prepare(`INSERT INTO benchmark (value) VALUES (?)`)

                for i := 0; i < largeCount; i++ {
                    stmt.Exec(i)

                    // 每10000条提交一次(避免事务过大)
                    if (i+1)%10000 == 0 {
                        stmt.Close()
                        tx.Commit()

                        tx, _ = db.Begin()
                        stmt, _ = tx.Prepare(`INSERT INTO benchmark (value) VALUES (?)`)
                    }
                }

                stmt.Close()
                tx.Commit()
                elapsed := time.Since(start)

                var total int
                db.QueryRow(`SELECT COUNT(*) FROM benchmark`).Scan(&total)

                fmt.Printf("\n总耗时: %v\n", elapsed)
                fmt.Printf("每秒插入: %.0f 条\n", float64(largeCount)/elapsed.Seconds())
                fmt.Printf("验证总数: %d\n", total)

                fmt.Println("\n批量插入建议:")
                fmt.Println("  1. 必须使用事务")
                fmt.Println("  2. 使用预编译语句")
                fmt.Println("  3. 合理分批(每批1000-10000)")
                fmt.Println("  4. 关闭同步模式(PRAGMA synchronous=OFF)")
            }
            ---
    b.预编译语句
        a.功能说明
            预编译语句(Prepared Statement)将SQL语句编译一次,重复执行时只需传入参数,避免重复解析SQL。对于批量操作,预编译可显著提升性能。使用db.Prepare或tx.Prepare创建,用完后必须Close释放资源。
        b.代码示例
            ---
            // 预编译语句最佳实践
            package main

            import (
                "database/sql"
                "fmt"
                "log"
                "time"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                db.Exec(`CREATE TABLE logs (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    level TEXT,
                    message TEXT,
                    timestamp INTEGER
                )`)

                fmt.Println("=== 预编译语句使用 ===\n")

                // 1. 基本预编译
                stmt, err := db.Prepare(`INSERT INTO logs (level, message, timestamp) VALUES (?, ?, ?)`)
                if err != nil {
                    log.Fatal(err)
                }
                defer stmt.Close()

                fmt.Println("1. 使用预编译语句插入:")
                result, _ := stmt.Exec("INFO", "应用启动", time.Now().Unix())
                id, _ := result.LastInsertId()
                fmt.Printf("   插入记录ID: %d\n", id)

                stmt.Exec("DEBUG", "加载配置", time.Now().Unix())
                stmt.Exec("INFO", "服务器监听端口8080", time.Now().Unix())
                stmt.Exec("WARN", "缓存未命中", time.Now().Unix())
                fmt.Println("   ✓ 批量插入完成\n")

                // 2. 在事务中使用预编译
                fmt.Println("2. 事务中的预编译语句:")
                tx, _ := db.Begin()
                txStmt, _ := tx.Prepare(`INSERT INTO logs (level, message, timestamp) VALUES (?, ?, ?)`)

                start := time.Now()
                for i := 0; i < 1000; i++ {
                    txStmt.Exec("INFO", fmt.Sprintf("消息#%d", i), time.Now().Unix())
                }

                txStmt.Close()
                tx.Commit()
                elapsed := time.Since(start)

                fmt.Printf("   插入1000条耗时: %v\n", elapsed)
                fmt.Printf("   每秒插入: %.0f 条\n\n", 1000/elapsed.Seconds())

                // 3. 查询预编译
                fmt.Println("3. 查询预编译语句:")
                queryStmt, _ := db.Prepare(`SELECT id, level, message FROM logs WHERE level = ? LIMIT ?`)
                defer queryStmt.Close()

                rows, _ := queryStmt.Query("INFO", 5)
                defer rows.Close()

                count := 0
                for rows.Next() {
                    var id int
                    var level, message string
                    rows.Scan(&id, &level, &message)
                    count++
                }
                fmt.Printf("   查询到 %d 条INFO日志\n\n", count)

                // 4. 更新预编译
                fmt.Println("4. 更新预编译语句:")
                updateStmt, _ := db.Prepare(`UPDATE logs SET level = ? WHERE level = ?`)
                defer updateStmt.Close()

                result, _ = updateStmt.Exec("WARNING", "WARN")
                affected, _ := result.RowsAffected()
                fmt.Printf("   更新了 %d 条记录\n\n", affected)

                // 5. 预编译陷阱:忘记Close
                fmt.Println("5. 资源管理(重要!):")
                fmt.Println("   ✓ 正确: defer stmt.Close()")
                fmt.Println("   ✗ 错误: 忘记Close导致资源泄漏")
                fmt.Println("   建议: 始终使用defer确保关闭\n")

                // 统计
                var totalLogs int
                db.QueryRow(`SELECT COUNT(*) FROM logs`).Scan(&totalLogs)
                fmt.Printf("最终日志总数: %d\n", totalLogs)

                fmt.Println("\n预编译使用场景:")
                fmt.Println("  ✓ 批量插入/更新")
                fmt.Println("  ✓ 重复执行的查询")
                fmt.Println("  ✓ 参数化SQL防注入")
                fmt.Println("  ✗ 一次性查询(开销大于收益)")
            }
            ---

03.INSERT扩展语法
    a.INSERT OR REPLACE
        a.功能说明
            INSERT OR REPLACE在主键或唯一约束冲突时删除旧行并插入新行,相当于REPLACE INTO。INSERT OR IGNORE在冲突时忽略插入。INSERT OR ABORT/FAIL/ROLLBACK控制冲突时的事务行为。
        b.代码示例
            ---
            // INSERT冲突处理策略
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, err := sql.Open("sqlite3", ":memory:")
                if err != nil {
                    log.Fatal(err)
                }
                defer db.Close()

                db.Exec(`CREATE TABLE configs (
                    key TEXT PRIMARY KEY,
                    value TEXT,
                    version INTEGER DEFAULT 1
                )`)

                fmt.Println("=== INSERT冲突处理 ===\n")

                // 初始数据
                db.Exec(`INSERT INTO configs VALUES ('theme', 'light', 1)`)
                db.Exec(`INSERT INTO configs VALUES ('language', 'zh-CN', 1)`)

                fmt.Println("1. INSERT OR REPLACE:")
                result, _ := db.Exec(`INSERT OR REPLACE INTO configs VALUES ('theme', 'dark', 2)`)
                affected, _ := result.RowsAffected()
                fmt.Printf("   影响行数: %d\n", affected)

                var theme string
                var version int
                db.QueryRow(`SELECT value, version FROM configs WHERE key = 'theme'`).Scan(&theme, &version)
                fmt.Printf("   主题: %s (版本: %d)\n\n", theme, version)

                // 2. INSERT OR IGNORE
                fmt.Println("2. INSERT OR IGNORE:")
                db.Exec(`INSERT OR IGNORE INTO configs VALUES ('theme', 'blue', 3)`)

                db.QueryRow(`SELECT value, version FROM configs WHERE key = 'theme'`).Scan(&theme, &version)
                fmt.Printf("   主题: %s (版本: %d)\n", theme, version)
                fmt.Println("   (保持原值,冲突被忽略)\n")

                // 3. ON CONFLICT子句(SQLite 3.24+)
                fmt.Println("3. ON CONFLICT DO UPDATE (UPSERT):")

                db.Exec(`
                    INSERT INTO configs (key, value, version) VALUES ('font_size', '14', 1)
                    ON CONFLICT(key) DO UPDATE SET
                        value = excluded.value,
                        version = version + 1
                `)

                db.Exec(`
                    INSERT INTO configs (key, value, version) VALUES ('font_size', '16', 1)
                    ON CONFLICT(key) DO UPDATE SET
                        value = excluded.value,
                        version = version + 1
                `)

                var fontSize string
                var fontVersion int
                db.QueryRow(`SELECT value, version FROM configs WHERE key = 'font_size'`).
                    Scan(&fontSize, &fontVersion)

                fmt.Printf("   字体大小: %s (版本: %d)\n", fontSize, fontVersion)
                fmt.Println("   (版本号自动递增)\n")

                // 4. ON CONFLICT DO NOTHING
                fmt.Println("4. ON CONFLICT DO NOTHING:")

                result, _ = db.Exec(`
                    INSERT INTO configs (key, value) VALUES ('language', 'en-US')
                    ON CONFLICT(key) DO NOTHING
                `)

                affected, _ = result.RowsAffected()
                fmt.Printf("   影响行数: %d (冲突被忽略)\n\n", affected)

                // 5. 查看所有配置
                fmt.Println("5. 最终配置:")
                rows, _ := db.Query(`SELECT key, value, version FROM configs ORDER BY key`)
                defer rows.Close()

                for rows.Next() {
                    var key, value string
                    var ver int
                    rows.Scan(&key, &value, &ver)
                    fmt.Printf("   %s = %s (v%d)\n", key, value, ver)
                }

                fmt.Println("\n策略选择:")
                fmt.Println("  INSERT OR REPLACE: 完全替换旧行")
                fmt.Println("  INSERT OR IGNORE: 保留旧行")
                fmt.Println("  ON CONFLICT DO UPDATE: 选择性更新字段(推荐)")
                fmt.Println("  ON CONFLICT DO NOTHING: 同IGNORE")
            }
            ---

2.5 查询数据

01.基本查询
    a.QueryRow方法
        a.功能说明
            QueryRow用于查询单行数据,返回*sql.Row对象。调用Scan方法将结果映射到Go变量。如果查询无结果返回sql.ErrNoRows错误,需要特殊处理与其他错误区分。
        b.代码示例
            ---
            // QueryRow详解
            package main

            import (
                "database/sql"
                "errors"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(`CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, age INTEGER)`)
                db.Exec(`INSERT INTO users VALUES (1, 'alice', 25), (2, 'bob', 30)`)

                fmt.Println("=== QueryRow使用 ===\n")

                // 查询存在的记录
                var username string
                var age int
                err := db.QueryRow(`SELECT username, age FROM users WHERE id = ?`, 1).Scan(&username, &age)
                if err != nil {
                    log.Fatal(err)
                }
                fmt.Printf("用户: %s, 年龄: %d\n", username, age)

                // 查询不存在的记录
                err = db.QueryRow(`SELECT username FROM users WHERE id = 999`).Scan(&username)
                if errors.Is(err, sql.ErrNoRows) {
                    fmt.Println("记录不存在")
                } else if err != nil {
                    log.Fatal(err)
                }
            }
            ---
    b.Query方法
        a.功能说明
            Query用于查询多行数据,返回*sql.Rows对象。必须遍历rows.Next()读取每一行,并在完成后调用rows.Close()释放资源。使用defer rows.Close()确保资源释放。
        b.代码示例
            ---
            // Query多行查询
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(`CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, price REAL)`)
                db.Exec(`INSERT INTO products VALUES (1, '笔记本', 5999), (2, '手机', 3999), (3, '平板', 2999)`)

                fmt.Println("=== Query多行查询 ===\n")

                rows, err := db.Query(`SELECT id, name, price FROM products WHERE price > ?`, 3000.0)
                if err != nil {
                    log.Fatal(err)
                }
                defer rows.Close()

                for rows.Next() {
                    var id int
                    var name string
                    var price float64
                    if err := rows.Scan(&id, &name, &price); err != nil {
                        log.Fatal(err)
                    }
                    fmt.Printf("ID:%d, 产品:%s, 价格:%.2f\n", id, name, price)
                }

                if err := rows.Err(); err != nil {
                    log.Fatal(err)
                }
            }
            ---

2.6 更新数据

01.UPDATE语句
    a.基本更新
        a.功能说明
            UPDATE语句修改表中的现有记录,使用SET子句指定新值,WHERE子句限定更新范围。不加WHERE会更新所有行,需谨慎使用。返回RowsAffected表示实际更新的行数。
        b.代码示例
            ---
            // UPDATE基础操作
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(`CREATE TABLE inventory (id INTEGER PRIMARY KEY, name TEXT, stock INTEGER)`)
                db.Exec(`INSERT INTO inventory VALUES (1, '笔记本', 50), (2, '手机', 100)`)

                fmt.Println("=== UPDATE操作 ===\n")

                // 单行更新
                result, err := db.Exec(`UPDATE inventory SET stock = ? WHERE id = ?`, 45, 1)
                if err != nil {
                    log.Fatal(err)
                }
                affected, _ := result.RowsAffected()
                fmt.Printf("更新行数: %d\n", affected)

                // 条件更新
                result, _ = db.Exec(`UPDATE inventory SET stock = stock - 10 WHERE stock > 50`)
                affected, _ = result.RowsAffected()
                fmt.Printf("库存调整: %d 个产品\n", affected)
            }
            ---

2.7 删除数据

01.DELETE语句
    a.基本删除
        a.功能说明
            DELETE FROM语句从表中删除记录,WHERE子句指定删除条件。不加WHERE会删除所有行但保留表结构。SQLite的DELETE不会立即释放磁盘空间,需要VACUUM回收。
        b.代码示例
            ---
            // DELETE基础操作
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(`CREATE TABLE logs (id INTEGER PRIMARY KEY, level TEXT, message TEXT, timestamp INTEGER)`)
                db.Exec(`INSERT INTO logs (level, message, timestamp) VALUES ('INFO', 'msg1', 1000), ('DEBUG', 'msg2', 2000), ('ERROR', 'msg3', 3000)`)

                fmt.Println("=== DELETE操作 ===\n")

                // 条件删除
                result, err := db.Exec(`DELETE FROM logs WHERE level = ?`, "DEBUG")
                if err != nil {
                    log.Fatal(err)
                }
                affected, _ := result.RowsAffected()
                fmt.Printf("删除DEBUG日志: %d 条\n", affected)

                // 时间范围删除
                result, _ = db.Exec(`DELETE FROM logs WHERE timestamp < ?`, 2500)
                affected, _ = result.RowsAffected()
                fmt.Printf("删除旧日志: %d 条\n", affected)

                // 验证剩余
                var count int
                db.QueryRow(`SELECT COUNT(*) FROM logs`).Scan(&count)
                fmt.Printf("剩余日志: %d 条\n", count)
            }
            ---

02.TRUNCATE替代
    a.DELETE全部数据
        a.功能说明
            SQLite不支持TRUNCATE语句,使用DELETE FROM table删除所有行。如果需要重置自增ID,需要DELETE后再DELETE FROM sqlite_sequence。或者直接DROP TABLE后重建表。
        b.代码示例
            ---
            // TRUNCATE模拟
            package main

            import (
                "database/sql"
                "fmt"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(`CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, value TEXT)`)
                db.Exec(`INSERT INTO test (value) VALUES ('a'), ('b'), ('c')`)

                // 清空数据
                db.Exec(`DELETE FROM test`)

                // 重置自增
                db.Exec(`DELETE FROM sqlite_sequence WHERE name='test'`)

                // 重新插入,ID从1开始
                result, _ := db.Exec(`INSERT INTO test (value) VALUES ('x')`)
                id, _ := result.LastInsertId()
                fmt.Printf("重置后新ID: %d\n", id)
            }
            ---

3 高级查询

3.1 条件查询

01.WHERE子句
    a.比较运算符
        a.功能说明
            WHERE子句通过条件表达式过滤查询结果。支持=、!=、<、>、<=、>=等比较运算符,以及AND、OR、NOT逻辑运算符。使用参数绑定防止SQL注入,保证查询安全。
        b.代码示例
            ---
            // WHERE条件查询示例
            package main

            import (
                "database/sql"
                "fmt"
                "log"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(`CREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT, age INTEGER, salary REAL, dept TEXT)`)
                db.Exec(`INSERT INTO employees VALUES (1, 'Alice', 25, 50000, 'IT'), (2, 'Bob', 30, 60000, 'Sales'), (3, 'Charlie', 35, 70000, 'IT')`)

                fmt.Println("=== WHERE条件查询 ===\n")

                // 等值查询
                rows, _ := db.Query(`SELECT name, salary FROM employees WHERE dept = ?`, "IT")
                defer rows.Close()

                fmt.Println("IT部门员工:")
                for rows.Next() {
                    var name string
                    var salary float64
                    rows.Scan(&name, &salary)
                    fmt.Printf("  %s: %.2f\n", name, salary)
                }

                // 范围查询
                rows2, _ := db.Query(`SELECT name, age FROM employees WHERE age BETWEEN ? AND ?`, 25, 32)
                defer rows2.Close()

                fmt.Println("\n25-32岁员工:")
                for rows2.Next() {
                    var name string
                    var age int
                    rows2.Scan(&name, &age)
                    fmt.Printf("  %s: %d岁\n", name, age)
                }

                // 复合条件
                rows3, _ := db.Query(`SELECT name FROM employees WHERE dept = ? AND salary > ?`, "IT", 55000)
                defer rows3.Close()

                fmt.Println("\nIT部门高薪员工:")
                for rows3.Next() {
                    var name string
                    rows3.Scan(&name)
                    fmt.Printf("  %s\n", name)
                }
            }
            ---
    b.模糊查询
        a.功能说明
            LIKE运算符用于模糊匹配,%匹配任意字符,%name%匹配包含name的字符串。_匹配单个字符。GLOB使用Unix风格通配符,*和?。
        b.代码示例
            ---
            // LIKE模糊查询
            package main

            import (
                "database/sql"
                "fmt"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(`CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, sku TEXT)`)
                db.Exec(`INSERT INTO products VALUES (1, 'iPhone 15', 'APL-IP15-BLK'), (2, 'iPad Air', 'APL-IPA-SLV'), (3, 'MacBook Pro', 'APL-MBP-GRY')`)

                fmt.Println("=== LIKE模糊查询 ===\n")

                // 前缀匹配
                rows, _ := db.Query(`SELECT name FROM products WHERE name LIKE ?`, "iP%")
                defer rows.Close()

                fmt.Println("iP开头的产品:")
                for rows.Next() {
                    var name string
                    rows.Scan(&name)
                    fmt.Printf("  %s\n", name)
                }

                // 包含匹配
                rows2, _ := db.Query(`SELECT name FROM products WHERE name LIKE ?`, "%Book%")
                defer rows2.Close()

                fmt.Println("\n包含Book的产品:")
                for rows2.Next() {
                    var name string
                    rows2.Scan(&name)
                    fmt.Printf("  %s\n", name)
                }

                // GLOB通配符
                rows3, _ := db.Query(`SELECT sku FROM products WHERE sku GLOB ?`, "APL-IP*")
                defer rows3.Close()

                fmt.Println("\nAPL-IP*的SKU:")
                for rows3.Next() {
                    var sku string
                    rows3.Scan(&sku)
                    fmt.Printf("  %s\n", sku)
                }
            }
            ---

02.IN和EXISTS
    a.IN子句
        a.功能说明
            IN运算符检查值是否在指定列表中。可以使用值列表或子查询。NOT IN检查不在列表中的值。
        b.代码示例
            ---
            // IN和NOT IN查询
            package main

            import (
                "database/sql"
                "fmt"

                _ "github.com/mattn/go-sqlite3"
            )

            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(`CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER, status TEXT, amount REAL)`)
                db.Exec(`INSERT INTO orders VALUES (1, 101, 'pending', 100), (2, 102, 'shipped', 200), (3, 103, 'delivered', 150), (4, 101, 'cancelled', 50)`)

                fmt.Println("=== IN查询 ===\n")

                // IN值列表
                rows, _ := db.Query(`SELECT id, status, amount FROM orders WHERE status IN (?, ?, ?)`, "pending", "shipped", "processing")
                defer rows.Close()

                fmt.Println("待处理订单:")
                for rows.Next() {
                    var id int
                    var status string
                    var amount float64
                    rows.Scan(&id, &status, &amount)
                    fmt.Printf("  订单%d: %s, %.2f元\n", id, status, amount)
                }

                // NOT IN
                rows2, _ := db.Query(`SELECT id FROM orders WHERE status NOT IN (?, ?)`, "cancelled", "refunded")
                defer rows2.Close()

                fmt.Println("\n有效订单ID:")
                for rows2.Next() {
                    var id int
                    rows2.Scan(&id)
                    fmt.Printf("  %d\n", id)
                }
            }
            ---

3.2 联表查询

01.基本概念
    a.功能说明
        JOIN操作用于合并多表数据。INNER JOIN返回匹配行,LEFT JOIN包含左表所有行,CROSS JOIN生成笛卡尔积。
    b.代码示例
        ---
        // JOIN示例
        package main

        import (
            "database/sql"
            "fmt"
            "log"

            _ "github.com/mattn/go-sqlite3"
        )

        func main() {
            db, _ := sql.Open("sqlite3", ":memory:")
            defer db.Close()

            db.Exec(\`CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)\`)
            db.Exec(\`CREATE TABLE orders (id INTEGER PRIMARY KEY, user_id INTEGER, amount REAL)\`)
            db.Exec(\`INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob')\`)
            db.Exec(\`INSERT INTO orders VALUES (1, 1, 100), (2, 1, 200), (3, 2, 150)\`)

            fmt.Println("=== JOIN查询 ===\\n")

            rows, _ := db.Query(\`SELECT u.name, o.amount FROM users u INNER JOIN orders o ON u.id = o.user_id\`)
            defer rows.Close()

            for rows.Next() {
                var name string
                var amount float64
                rows.Scan(&name, &amount)
                fmt.Printf("%s: %.2f元\\n", name, amount)
            }
                    }
                    ---

3.3 聚合函数

01.基本概念
    a.功能说明
        聚合函数对多行数据进行计算返回单个值。常用函数包括COUNT、SUM、AVG、MAX、MIN等。
    b.代码示例
        ---
        // 聚合函数示例
        package main

        import (
            "database/sql"
            "fmt"
            "log"

            _ "github.com/mattn/go-sqlite3"
        )

        func main() {
            db, _ := sql.Open("sqlite3", ":memory:")
            defer db.Close()

            db.Exec(\`CREATE TABLE sales (id INTEGER PRIMARY KEY, product TEXT, quantity INTEGER, price REAL)\`)
        db.Exec(\`INSERT INTO sales VALUES (1, 'A', 10, 100), (2, 'B', 5, 200), (3, 'A', 8, 100)\`)

        fmt.Println("=== 聚合函数 ===\\n")

        var count int
        var totalQty int
        var avgPrice, maxPrice float64

        db.QueryRow(\`SELECT COUNT(*), SUM(quantity), AVG(price), MAX(price) FROM sales\`).Scan(&count, &totalQty, &avgPrice, &maxPrice)

        fmt.Printf("记录数: %d\\n总数量: %d\\n平均价格: %.2f\\n最高价格: %.2f\\n", count, totalQty, avgPrice, maxPrice)
        }
        ---

3.4 分组排序

01.基本概念
    a.功能说明
        GROUP BY对结果分组,HAVING过滤分组,ORDER BY排序结果。支持ASC升序和DESC降序,LIMIT限制返回行数。
    b.代码示例
        ---
        // GROUP BY/ORDER BY示例
        package main

        import (
            "database/sql"
            "fmt"
            "log"

            _ "github.com/mattn/go-sqlite3"
        )

        func main() {
            db, _ := sql.Open("sqlite3", ":memory:")
            defer db.Close()

            db.Exec(\`CREATE TABLE transactions (id INTEGER PRIMARY KEY, category TEXT, amount REAL)\`)
        db.Exec(\`INSERT INTO transactions VALUES (1, 'Food', 50), (2, 'Food', 80), (3, 'Travel', 200)\`)

        fmt.Println("=== GROUP BY/ORDER BY ===\\n")

        rows, _ := db.Query(\`SELECT category, SUM(amount) as total FROM transactions GROUP BY category ORDER BY total DESC\`)
        defer rows.Close()

        for rows.Next() {
            var category string
            var total float64
            rows.Scan(&category, &total)
            fmt.Printf("%s: %.2f元\\n", category, total)
        }
                }
                ---

3.5 子查询

01.基本概念
    a.功能说明
        子查询是嵌套在其他查询中的SELECT语句。可用于WHERE、FROM、SELECT子句中,支持标量和表子查询。
    b.代码示例
        ---
        // 子查询示例
        package main

        import (
            "database/sql"
            "fmt"
            "log"

            _ "github.com/mattn/go-sqlite3"
        )

        func main() {
            db, _ := sql.Open("sqlite3", ":memory:")
            defer db.Close()

            db.Exec(\`CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, price REAL)\`)
        db.Exec(\`INSERT INTO products VALUES (1, 'A', 100), (2, 'B', 200), (3, 'C', 150)\`)

        fmt.Println("=== 子查询 ===\\n")

        var avgPrice float64
        db.QueryRow(\`SELECT AVG(price) FROM products\`).Scan(&avgPrice)

        rows, _ := db.Query(\`SELECT name, price FROM products WHERE price > (SELECT AVG(price) FROM products)\`)
        defer rows.Close()

        fmt.Printf("高于平均价(%.2f)的产品:\\n", avgPrice)
        for rows.Next() {
            var name string
            var price float64
            rows.Scan(&name, &price)
            fmt.Printf("  %s: %.2f\\n", name, price)
        }
                }
                ---

3.6 索引优化

01.基本概念
    a.功能说明
        索引加速查询性能,CREATE INDEX创建索引。索引占用空间但显著提升WHERE、JOIN、ORDER BY性能。
    b.代码示例
        ---
        // 索引示例
        package main

        import (
            "database/sql"
            "fmt"
            "log"

            _ "github.com/mattn/go-sqlite3"
        )

        func main() {
            db, _ := sql.Open("sqlite3", ":memory:")
            defer db.Close()

            db.Exec(\`CREATE TABLE large_table (id INTEGER PRIMARY KEY, code TEXT, value INTEGER)\`)

        stmt, _ := db.Prepare(\`INSERT INTO large_table (code, value) VALUES (?, ?)\`)
        for i := 0; i < 10000; i++ {
            stmt.Exec(fmt.Sprintf("CODE%d", i), i)
        }
        stmt.Close()

        fmt.Println("=== 索引性能 ===\\n")

        // 无索引查询
        start := time.Now()
        db.QueryRow(\`SELECT value FROM large_table WHERE code = ?\`, "CODE5000").Scan(new(int))
        fmt.Printf("无索引耗时: %v\\n", time.Since(start))

        // 创建索引
        db.Exec(\`CREATE INDEX idx_code ON large_table(code)\`)

        // 有索引查询
        start = time.Now()
        db.QueryRow(\`SELECT value FROM large_table WHERE code = ?\`, "CODE5000").Scan(new(int))
        fmt.Printf("有索引耗时: %v\\n", time.Since(start))
        }
        ---

4 事务与并发

4.1 事务基础

01.核心概念
    a.ACID特性
        a.功能说明
            事务通过Begin、Commit、Rollback保证ACID。db.Begin()开始事务,tx.Commit()提交,tx.Rollback()回滚。
        b.代码示例
            ---
            // 事务操作
            package main
            import ("database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(\`CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance REAL)\`)
                db.Exec(\`INSERT INTO accounts VALUES (1, 1000)\`)
                tx, _ := db.Begin()
                tx.Exec(\`UPDATE accounts SET balance = balance - 100 WHERE id = 1\`)
                tx.Commit()
                var balance float64
                db.QueryRow(\`SELECT balance FROM accounts WHERE id = 1\`).Scan(&balance)
                fmt.Printf("余额: %.2f\n", balance)
            }
            ---

4.2 事务隔离级别

01.核心概念
    a.隔离级别
        a.功能说明
            SQLite支持READ UNCOMMITTED和SERIALIZABLE隔离级别。通过PRAGMA read_uncommitted设置。
        b.代码示例
            ---
            // 隔离级别
            package main
            import ("database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(\`PRAGMA read_uncommitted = 1\`)
                var ru int
                db.QueryRow(\`PRAGMA read_uncommitted\`).Scan(&ru)
                fmt.Printf("隔离级别: %d\n", ru)
            }
            ---

4.3 并发控制

01.核心概念
    a.并发模式
        a.功能说明
            WAL模式支持读写并发,DELETE模式读写互斥。多个读可并发,写操作串行化。
        b.代码示例
            ---
            // 并发测试
            package main
            import ("database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(\`CREATE TABLE test (id INTEGER)\`)
                done := make(chan bool)
                go func() { db.Exec(\`INSERT INTO test VALUES (1)\`); done <- true }()
                go func() { db.Exec(\`INSERT INTO test VALUES (2)\`); done <- true }()
                <-done; <-done
                var count int
                db.QueryRow(\`SELECT COUNT(*) FROM test\`).Scan(&count)
                fmt.Printf("插入: %d条\n", count)
            }
            ---

4.4 锁机制

01.核心概念
    a.锁类型
        a.功能说明
            SQLite使用5级锁:UNLOCKED、SHARED、RESERVED、PENDING、EXCLUSIVE。文件级锁限制并发写。
        b.代码示例
            ---
            // 锁演示
            package main
            import ("database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(\`CREATE TABLE locks (id INTEGER)\`)
                tx, _ := db.Begin()
                tx.Exec(\`INSERT INTO locks VALUES (1)\`)
                fmt.Println("事务持有RESERVED锁")
                tx.Commit()
                fmt.Println("锁已释放")
            }
            ---

4.5 错误处理

01.核心概念
    a.错误恢复
        a.功能说明
            SQLITE_BUSY错误表示数据库锁定,设置busy_timeout等待。事务失败需回滚避免部分提交。
        b.代码示例
            ---
            // 错误处理
            package main
            import ("database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()

                db.Exec(\`CREATE TABLE test (id INTEGER UNIQUE)\`)
                tx, _ := db.Begin()
                _, err := tx.Exec(\`INSERT INTO test VALUES (1), (1)\`)
                if err != nil {
                    tx.Rollback()
                    fmt.Printf("错误已回滚: %v\n", err)
                } else {
                    tx.Commit()
                }
            }
            ---

5 性能优化

5.1 连接池配置

01.优化技术
    a.连接池
        a.功能说明
            SetMaxOpenConns(1)避免锁竞争,SetMaxIdleConns(1)保持连接,SetConnMaxLifetime控制生命周期。
        b.代码示例
            ---
            package main
            import ("database/sql"; "fmt"; "time"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()
                db.SetMaxOpenConns(1)
                db.SetMaxIdleConns(1)
                db.SetConnMaxLifetime(time.Hour)
                stats := db.Stats()
                fmt.Printf("最大连接: %d\n", stats.MaxOpenConnections)
            }
            ---

5.2 预编译语句

01.优化技术
    a.预编译
        a.功能说明
            Prepare编译一次重复使用,批量操作提升性能。事务内使用预编译语句效果最佳。
        b.代码示例
            ---
            package main
            import ("database/sql"; "fmt"; "time"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()
                db.Exec(\`CREATE TABLE test (value INTEGER)\`)
                stmt, _ := db.Prepare(\`INSERT INTO test VALUES (?)\`)
                defer stmt.Close()
                for i := 0; i < 100; i++ { stmt.Exec(i) }
            }
            ---

5.3 批量操作

01.优化技术
    a.批量处理
        a.功能说明
            批量INSERT使用事务+预编译,每批1000-10000条。关闭synchronous提速。
        b.代码示例
            ---
            package main
            import ("database/sql"; "fmt"; "time"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()
                db.Exec(\`CREATE TABLE bench (id INTEGER)\`)
                tx, _ := db.Begin()
                stmt, _ := tx.Prepare(\`INSERT INTO bench VALUES (?)\`)
                for i := 0; i < 10000; i++ { stmt.Exec(i) }
                stmt.Close()
                tx.Commit()
                fmt.Println("批量插入完成")
            }
            ---

5.4 内存模式

01.优化技术
    a.内存数据库
        a.功能说明
            :memory:创建内存数据库,速度极快但数据易失。适合临时数据和测试。
        b.代码示例
            ---
            package main
            import ("database/sql"; "fmt"; "time"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()
                db.Exec(\`CREATE TABLE cache (key TEXT, val TEXT)\`)
                db.Exec(\`INSERT INTO cache VALUES ('k1', 'v1')\`)
                var val string
                db.QueryRow(\`SELECT val FROM cache WHERE key='k1'\`).Scan(&val)
                fmt.Printf("缓存值: %s\n", val)
            }
            ---

5.5 WAL模式

01.优化技术
    a.WAL日志
        a.功能说明
            PRAGMA journal_mode=WAL启用,支持读写并发,checkpoint合并数据。
        b.代码示例
            ---
            package main
            import ("database/sql"; "fmt"; "time"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", "file::memory:?_journal_mode=WAL")
                defer db.Close()
                var mode string
                db.QueryRow(\`PRAGMA journal_mode\`).Scan(&mode)
                fmt.Printf("日志模式: %s\n", mode)
                db.Exec(\`CREATE TABLE wal_test (id INTEGER)\`)
                db.Exec(\`PRAGMA wal_checkpoint(FULL)\`)
                fmt.Println("Checkpoint完成")
            }
            ---

5.6 性能监控

01.优化技术
    a.监控指标
        a.功能说明
            db.Stats()获取连接池统计,EXPLAIN QUERY PLAN分析查询,ANALYZE更新统计信息。
        b.代码示例
            ---
            package main
            import ("database/sql"; "fmt"; "time"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", ":memory:")
                defer db.Close()
                db.Exec(\`CREATE TABLE perf (id INTEGER PRIMARY KEY, val INTEGER)\`)
                for i := 0; i < 1000; i++ { db.Exec(\`INSERT INTO perf VALUES (?, ?)\`, i, i*2) }
                rows, _ := db.Query(\`EXPLAIN QUERY PLAN SELECT * FROM perf WHERE id > 500\`)
                defer rows.Close()
                fmt.Println("查询计划:")
                for rows.Next() {
                    var detail string
                    rows.Scan(new(int), new(int), new(int), &detail)
                    fmt.Println(detail)
                }
            }
            ---

6 实战应用

6.1 安装配置

01.实践指南
    a.依赖安装
        a.功能说明
            go get github.com/mattn/go-sqlite3安装驱动,需要CGO环境。modernc.org/sqlite纯Go无需CGO。
        b.代码示例
            ---
            package main
            import ( "database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, err := sql.Open("sqlite3", "./app.db")
                if err != nil { panic(err) }
                defer db.Close()
                if err := db.Ping(); err != nil { panic(err) }
                fmt.Println("SQLite连接成功")
                var version string
                db.QueryRow("SELECT sqlite_version()").Scan(&version)
                fmt.Printf("SQLite版本: %s\n", version)
            }
            ---

02.最佳实践
    a.生产建议
        a.要点
            使用WAL模式提升并发,设置合理的busy_timeout,启用外键约束,定期VACUUM优化。

6.2 ORM集成

01.实践指南
    a.GORM
        a.功能说明
            GORM是Go流行ORM,支持SQLite。gorm.Open(sqlite.Open())连接,AutoMigrate自动迁移。
        b.代码示例
            ---
            package main
            import ("gorm.io/driver/sqlite"; "gorm.io/gorm"; "database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            type User struct { ID uint; Name string }
            func main() {
                db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})
                if err != nil { panic(err) }
                db.AutoMigrate(&User{})
                db.Create(&User{Name: "Alice"})
                var user User
                db.First(&user, 1)
                fmt.Printf("用户: %s\n", user.Name)
            }
            ---

02.最佳实践
    a.生产建议
        a.要点
            ORM提升开发效率但有性能开销,复杂查询使用原生SQL,注意N+1查询问题。

6.3 数据迁移

01.实践指南
    a.版本管理
        a.功能说明
            golang-migrate管理数据库版本,支持up/down迁移。编写SQL文件实现schema演进。
        b.代码示例
            ---
            package main
            import ( "database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", "./migrate.db")
                defer db.Close()
                _, err := db.Exec(\`CREATE TABLE IF NOT EXISTS schema_version (version INTEGER)\`)
                if err == nil {
                    db.Exec(\`INSERT INTO schema_version VALUES (1)\`)
                    fmt.Println("迁移v1完成")
                }
            }
            ---

02.最佳实践
    a.生产建议
        a.要点
            版本化管理schema变更,编写可逆迁移,测试迁移脚本,备份后再执行生产迁移。

6.4 备份恢复

01.实践指南
    a.备份策略
        a.功能说明
            使用VACUUM INTO导出,文件复制简单备份。在线备份使用SQLite Backup API。
        b.代码示例
            ---
            package main
            import ( "database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            func main() {
                srcDB, _ := sql.Open("sqlite3", "./source.db")
                srcDB.Exec(\`CREATE TABLE data (id INTEGER, val TEXT)\`)
                srcDB.Exec(\`INSERT INTO data VALUES (1, 'test')\`)
                srcDB.Exec(\`VACUUM INTO 'backup.db'\`)
                srcDB.Close()
                fmt.Println("备份到backup.db")
            }
            ---

02.最佳实践
    a.生产建议
        a.要点
            定期自动备份,验证备份完整性,使用PRAGMA integrity_check,异地存储备份文件。

6.5 嵌入式应用

01.实践指南
    a.嵌入式
        a.功能说明
            嵌入式设备使用SQLite存储配置和日志,关闭同步模式减少写入,定期清理旧数据。
        b.代码示例
            ---
            package main
            import ( "database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", "./embedded.db?_synchronous=OFF")
                defer db.Close()
                db.Exec(\`CREATE TABLE IF NOT EXISTS sensor_data (ts INTEGER, temp REAL)\`)
                db.Exec(\`INSERT INTO sensor_data VALUES (?, ?)\`, 1234567890, 25.5)
                db.Exec(\`DELETE FROM sensor_data WHERE ts < ?\`, 1234560000)
                fmt.Println("嵌入式数据库操作完成")
            }
            ---

02.最佳实践
    a.生产建议
        a.要点
            限制数据库大小,使用内存模式临时数据,批量写入减少磨损,错误处理完善。

6.6 常见问题

01.实践指南
    a.FAQ
        a.功能说明
            database locked错误增加busy_timeout,UNIQUE约束使用INSERT OR IGNORE,类型转换注意动态类型系统。
        b.代码示例
            ---
            package main
            import ( "database/sql"; "fmt"; _ "github.com/mattn/go-sqlite3")
            func main() {
                db, _ := sql.Open("sqlite3", "./faq.db?_busy_timeout=5000")
                defer db.Close()
                db.Exec(\`CREATE TABLE test (id INTEGER UNIQUE)\`)
                db.Exec(\`INSERT OR IGNORE INTO test VALUES (1)\`)
                db.Exec(\`INSERT OR IGNORE INTO test VALUES (1)\`)
                var count int
                db.QueryRow(\`SELECT COUNT(*) FROM test\`).Scan(&count)
                fmt.Printf("去重后记录数: %d\n", count)
            }
            ---

02.最佳实践
    a.生产建议
        a.要点
            监控数据库大小,记录慢查询,使用索引优化,避免SELECT *,参数化查询防注入。