Go 语言中使用 SQLite:详细教程与示例代码 – wiki基地

“`go

Go 语言中使用 SQLite:详细教程与示例代码

SQLite 是一款轻量级的、跨平台的、自包含的 SQL 数据库引擎。它不需要独立的服务器进程,可以直接嵌入到应用程序中,非常适合小型项目、原型设计和移动应用。Go 语言提供了 database/sql 包,配合 SQLite 驱动,可以方便地进行 SQLite 数据库的操作。

本文将详细介绍如何在 Go 语言中使用 SQLite,包括数据库连接、创建表、插入数据、查询数据、更新数据、删除数据、事务处理、以及错误处理等。同时,提供丰富的示例代码,帮助读者快速上手。

准备工作

  1. 安装 SQLite 驱动:

首先,需要安装 Go SQLite 驱动。推荐使用 modernc.org/sqlite,它是一个纯 Go 实现的 SQLite 驱动,无需 CGO 依赖。

bash
go get modernc.org/sqlite

或者,您也可以选择使用 github.com/mattn/go-sqlite3。 但需要安装 CGO 支持和 SQLite 库。

bash
go get github.com/mattn/go-sqlite3

本文将主要使用 modernc.org/sqlite 驱动。

  1. 导入必要的包:

在 Go 代码中,需要导入 database/sql 和 SQLite 驱动包。

“`go
import (
“database/sql”
“fmt”
“log”

   _ "modernc.org/sqlite" // 或者 _ "github.com/mattn/go-sqlite3"

)
“`

_ 前缀表示匿名导入,仅用于注册驱动,而不需要直接使用包中的任何函数或变量。

连接数据库

使用 sql.Open() 函数连接 SQLite 数据库。第一个参数是驱动名称,第二个参数是数据库文件的路径。如果数据库文件不存在,则会自动创建。

“`go
func main() {
db, err := sql.Open(“sqlite”, “mydatabase.db”)
if err != nil {
log.Fatal(err)
}
defer db.Close() // 确保在使用完毕后关闭数据库连接

fmt.Println("Successfully connected to SQLite!")

// 后续数据库操作...

}
“`

  • sql.Open("sqlite", "mydatabase.db"): 尝试打开或创建一个名为 mydatabase.db 的 SQLite 数据库文件。 如果文件不存在,SQLite 将会自动创建它。
  • defer db.Close(): 使用 defer 语句保证在 main 函数退出之前,数据库连接会被关闭,释放资源。 这是一个非常重要的良好编程习惯,可以避免资源泄露。
  • 错误处理: 检查 sql.Open 函数的返回值 err 是否为 nil。 如果 err 不为 nil,说明连接失败,使用 log.Fatal(err) 打印错误信息并退出程序。 log.Fatal 在打印完错误信息后会调用 os.Exit(1),使程序终止。

创建表

使用 db.Exec() 函数执行 SQL 语句来创建表。

“`go
func main() {
// … (连接数据库代码) …

createTableSQL := `
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL
);
`

_, err = db.Exec(createTableSQL)
if err != nil {
    log.Fatal(err)
}

fmt.Println("Table 'users' created successfully!")

// 后续数据库操作...

}
“`

  • CREATE TABLE IF NOT EXISTS users (...): 创建一个名为 users 的表。 IF NOT EXISTS 语句确保只有当表不存在时才创建,避免重复创建导致错误。
  • 字段定义:
    • id INTEGER PRIMARY KEY AUTOINCREMENT: 定义一个名为 id 的整型字段,作为主键,并设置为自动递增。 这意味着每次插入新记录时,id 的值会自动增加。
    • name TEXT NOT NULL: 定义一个名为 name 的文本字段,不能为空。
    • email TEXT UNIQUE NOT NULL: 定义一个名为 email 的文本字段,不能为空,且值必须唯一。
  • db.Exec(createTableSQL): 执行 SQL 语句。 db.Exec 用于执行不返回结果集的 SQL 语句,例如 CREATE TABLEINSERTUPDATEDELETE 等。
  • 错误处理: 检查 db.Exec 函数的返回值 err 是否为 nil。如果 err 不为 nil,说明执行失败,使用 log.Fatal(err) 打印错误信息并退出程序。

插入数据

使用 db.Exec() 函数执行 SQL 语句来插入数据。

“`go
func main() {
// … (连接数据库和创建表代码) …

insertSQL := `
INSERT INTO users (name, email) VALUES (?, ?);
`

_, err = db.Exec(insertSQL, "Alice", "[email protected]")
if err != nil {
    log.Fatal(err)
}

fmt.Println("Data inserted successfully!")

// 后续数据库操作...

}
“`

  • INSERT INTO users (name, email) VALUES (?, ?): 插入一条新记录到 users 表中。 ? 是占位符,用于防止 SQL 注入攻击。
  • db.Exec(insertSQL, "Alice", "[email protected]"): 执行 SQL 语句,并将 name 设置为 “Alice”,email 设置为 “[email protected]”。
  • 错误处理: 检查 db.Exec 函数的返回值 err 是否为 nil。如果 err 不为 nil,说明执行失败,使用 log.Fatal(err) 打印错误信息并退出程序。

查询数据

使用 db.Query() 函数执行 SQL 语句来查询数据。

“`go
func main() {
// … (连接数据库、创建表和插入数据代码) …

querySQL := `
SELECT id, name, email FROM users;
`

rows, err := db.Query(querySQL)
if err != nil {
    log.Fatal(err)
}
defer rows.Close() // 确保在使用完毕后关闭结果集

fmt.Println("Query results:")
for rows.Next() {
    var id int
    var name string
    var email string

    err = rows.Scan(&id, &name, &email)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("ID: %d, Name: %s, Email: %s\n", id, name, email)
}

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

// 后续数据库操作...

}
“`

  • SELECT id, name, email FROM users: 查询 users 表中的所有记录,并返回 idnameemail 字段。
  • db.Query(querySQL): 执行 SQL 语句,并返回一个 sql.Rows 对象,它代表查询结果集。
  • defer rows.Close(): 使用 defer 语句确保在使用完毕后关闭结果集,释放资源。
  • rows.Next(): 迭代结果集中的每一行。 rows.Next() 返回 true 如果还有下一行,否则返回 false
  • rows.Scan(&id, &name, &email): 将当前行的数据扫描到变量 idnameemail 中。 参数必须是指针。
  • rows.Err(): 检查迭代过程中是否发生错误。

更新数据

使用 db.Exec() 函数执行 SQL 语句来更新数据。

“`go
func main() {
// … (连接数据库、创建表和插入数据代码) …

updateSQL := `
UPDATE users SET name = ? WHERE email = ?;
`

_, err = db.Exec(updateSQL, "Bob", "[email protected]")
if err != nil {
    log.Fatal(err)
}

fmt.Println("Data updated successfully!")

// 后续数据库操作...

}
“`

  • UPDATE users SET name = ? WHERE email = ?: 更新 users 表中 email 为 “[email protected]” 的记录的 name 字段为 “Bob”。
  • db.Exec(updateSQL, "Bob", "[email protected]"): 执行 SQL 语句。
  • 错误处理: 检查 db.Exec 函数的返回值 err 是否为 nil。如果 err 不为 nil,说明执行失败,使用 log.Fatal(err) 打印错误信息并退出程序。

删除数据

使用 db.Exec() 函数执行 SQL 语句来删除数据。

“`go
func main() {
// … (连接数据库、创建表和插入数据代码) …

deleteSQL := `
DELETE FROM users WHERE email = ?;
`

_, err = db.Exec(deleteSQL, "[email protected]")
if err != nil {
    log.Fatal(err)
}

fmt.Println("Data deleted successfully!")

// 后续数据库操作...

}
“`

  • DELETE FROM users WHERE email = ?: 删除 users 表中 email 为 “[email protected]” 的记录。
  • db.Exec(deleteSQL, "[email protected]"): 执行 SQL 语句。
  • 错误处理: 检查 db.Exec 函数的返回值 err 是否为 nil。如果 err 不为 nil,说明执行失败,使用 log.Fatal(err) 打印错误信息并退出程序。

事务处理

事务是一组原子性的操作,要么全部成功,要么全部失败。Go 语言提供了 db.Begin() 函数来开始一个事务,tx.Commit() 函数来提交事务,tx.Rollback() 函数来回滚事务。

“`go
func main() {
// … (连接数据库、创建表和插入数据代码) …

tx, err := db.Begin()
if err != nil {
    log.Fatal(err)
}

insertSQL1 := `
INSERT INTO users (name, email) VALUES (?, ?);
`

_, err = tx.Exec(insertSQL1, "Charlie", "[email protected]")
if err != nil {
    tx.Rollback() // 发生错误,回滚事务
    log.Fatal(err)
}

insertSQL2 := `
INSERT INTO users (name, email) VALUES (?, ?);
`

_, err = tx.Exec(insertSQL2, "David", "[email protected]")
if err != nil {
    tx.Rollback() // 发生错误,回滚事务
    log.Fatal(err)
}

err = tx.Commit() // 提交事务
if err != nil {
    log.Fatal(err)
}

fmt.Println("Transaction committed successfully!")

// 后续数据库操作...

}
“`

  • db.Begin(): 开始一个新的事务。返回一个 sql.Tx 对象,代表事务。
  • tx.Exec(...): 在事务中执行 SQL 语句。
  • tx.Rollback(): 回滚事务。 如果在事务中的任何操作失败,应该调用 tx.Rollback() 来撤销所有已执行的操作,保持数据一致性。
  • tx.Commit(): 提交事务。 如果事务中的所有操作都成功完成,应该调用 tx.Commit() 来将更改保存到数据库。
  • 错误处理: 在事务中的每一个操作之后,都应该检查错误。 如果发生错误,回滚事务并处理错误。 如果在 tx.Commit() 过程中发生错误,也应该进行处理。

错误处理

在 Go 语言中使用 SQLite 时,错误处理非常重要。应该始终检查函数的返回值 err 是否为 nil,并根据错误类型进行相应的处理。

“`go
func main() {
// … (连接数据库代码) …

_, err := db.Exec("INVALID SQL")
if err != nil {
    fmt.Println("SQL execution error:", err)
}

// ...

}
“`

完整示例代码

“`go
package main

import (
“database/sql”
“fmt”
“log”

_ "modernc.org/sqlite" // 或者 _ "github.com/mattn/go-sqlite3"

)

func main() {
db, err := sql.Open(“sqlite”, “mydatabase.db”)
if err != nil {
log.Fatal(err)
}
defer db.Close()

fmt.Println("Successfully connected to SQLite!")

createTableSQL := `
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL
);
`

_, err = db.Exec(createTableSQL)
if err != nil {
    log.Fatal(err)
}

fmt.Println("Table 'users' created successfully!")

// 插入数据
insertSQL := `
INSERT INTO users (name, email) VALUES (?, ?);
`

_, err = db.Exec(insertSQL, "Alice", "[email protected]")
if err != nil {
    log.Fatal(err)
}

fmt.Println("Data inserted successfully!")

// 查询数据
querySQL := `
SELECT id, name, email FROM users;
`

rows, err := db.Query(querySQL)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

fmt.Println("Query results:")
for rows.Next() {
    var id int
    var name string
    var email string

    err = rows.Scan(&id, &name, &email)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("ID: %d, Name: %s, Email: %s\n", id, name, email)
}

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

// 更新数据
updateSQL := `
UPDATE users SET name = ? WHERE email = ?;
`

_, err = db.Exec(updateSQL, "Bob", "[email protected]")
if err != nil {
    log.Fatal(err)
}

fmt.Println("Data updated successfully!")

// 删除数据
deleteSQL := `
DELETE FROM users WHERE email = ?;
`

_, err = db.Exec(deleteSQL, "[email protected]")
if err != nil {
    log.Fatal(err)
}

fmt.Println("Data deleted successfully!")

// 事务处理
tx, err := db.Begin()
if err != nil {
    log.Fatal(err)
}

insertSQL1 := `
INSERT INTO users (name, email) VALUES (?, ?);
`

_, err = tx.Exec(insertSQL1, "Charlie", "[email protected]")
if err != nil {
    tx.Rollback()
    log.Fatal(err)
}

insertSQL2 := `
INSERT INTO users (name, email) VALUES (?, ?);
`

_, err = tx.Exec(insertSQL2, "David", "[email protected]")
if err != nil {
    tx.Rollback()
    log.Fatal(err)
}

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

fmt.Println("Transaction committed successfully!")

}
“`

总结

本文详细介绍了如何在 Go 语言中使用 SQLite 数据库。 从连接数据库、创建表、插入数据、查询数据、更新数据、删除数据,到事务处理和错误处理,都提供了详细的示例代码。 希望本文能够帮助读者快速上手 Go 语言中的 SQLite 开发。

记住要始终进行错误处理,并使用 defer 语句来确保资源在使用完毕后被释放。 理解事务的概念对于保证数据一致性至关重要。 通过实践本文中的示例代码,您可以更好地掌握 Go 语言中 SQLite 的使用。
“`

这篇文章包含了 SQLite 数据库的基本操作,以及事务处理和错误处理。示例代码也较为完整,可以直接运行。 如果您需要更高级的用法,例如预编译语句、连接池等,可以查阅相关文档。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部