ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

在 Go 中使用 SQLite:从 `database/sql` 驱动选型到 CRUD 与事务实战(build-web-application-with-golang 第 5.3 节)

在 Go 中使用 SQLite:从 `database/sql` 驱动选型到 CRUD 与事务实战(build-web-application-with-golang 第 5.3 节) 文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载SQLite 是一款开源的嵌入式关系型数据库具备零配置、自包含、支持事务等特点非常适合作为 Web 应用的轻量级数据存储。本文以《Build Web Application with Golang》第 5.3 节俄文版 ru/05.3.md为核心结合仓库内 ch.5.3 示例源码完整讲解如何在 Go 中通过标准database/sql接口驱动 SQLite掌握建表、增删改查、结果集读取与事务提交/回滚的完整实战流程读完即可独立写出可迁移的 SQLite 数据访问代码。SQLite嵌入式关系数据库的核心特性SQLite 是开源的、可嵌入的embedded关系型数据库它的引擎是自包含self-contained、零配置zero-configuration且支持事务的。它具备高度可移植、易用、紧凑、高效和可靠的特点。大多数情况下你只需要一个 SQLite 的二进制文件就可以完成数据库的创建、连接和操作——不需要独立的服务端进程也不需要进行复杂的安装配置。如果你正在寻找一个嵌入式数据库解决方案SQLite 是值得优先考虑的候选可以说SQLite 就是开源世界里的 Access微软桌面数据库版本。对于本书第 5 章数据库这一系列章节而言SQLite 与 MySQL、PostgreSQL 共同构成了三种主流选型其中 SQLite 最适合原型验证、单机应用与嵌入式场景。Go 生态中的 SQLite 驱动对比Go 中针对 SQLite 的数据库驱动有很多但其中相当一部分并不支持标准接口database/sql。第 5.3 节列举了三款典型驱动它们都基于 cgo 实现驱动是否支持database/sql实现方式mattn/go-sqlite3✅ 支持基于 cgofeyeleanor/gosqlite3❌ 不支持基于 cgophf/go-sqlite3❌ 不支持基于 cgo在三者之中mattn/go-sqlite3 是唯一支持database/sql接口标准的驱动这也是本节示例以及本书作者项目选择它的原因。支持标准接口带来的最大好处是你的业务代码与底层数据库解耦未来如果需要迁移到其他数据库例如 MySQL只需更换驱动注册方式与连接参数而database/sql之上的业务逻辑可以基本保持不变。需要说明的是由于该驱动基于 cgo运行环境需要具备 C 编译器与 SQLite 原生库支持同时它的注册名是sqlite3在sql.Open时必须与之严格对应。建表userinfo表结构在第 5 章的各个数据库小节中作者刻意使用了相同逻辑的表结构来演示不同数据库驱动的用法方便读者横向对比。SQLite 版本的表结构如下CREATE TABLE userinfo ( uid INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR(64) NULL, department VARCHAR(64) NULL, created DATE NULL );该建表语句与 示例目录中的 schema.sql 完全一致。各字段含义uid整型主键AUTOINCREMENT保证自增且不重用已删除的行号username用户名可变长字符串允许为空department部门可变长字符串允许为空created创建日期DATE 类型允许为空。需要注意的是SQLite 本身对类型是弱约束的采用动态类型系统但在 Go 侧通过database/sql扫描结果时仍会按目标变量的类型进行转换因此保持字段类型与 Go 变量类型的一致性是减少Scan错误的良好习惯。完整 CRUD 示例插入、更新、查询与删除第 5.3 节给出了一个完整的 Go 程序展示基于database/sql标准的全部四类操作。这里以仓库内 完整可运行的 main.go 为基准该书英文版对示例做了细节增强如使用time.Now().Format(2006-01-02)动态生成日期、打印更可读的输出其核心逻辑如下package main import ( database/sql fmt _ github.com/mattn/go-sqlite3 time ) const DB_PATH ./foo.db func main() { db, err : sql.Open(sqlite3, DB_PATH) checkErr(err) defer db.Close() // 插入 stmt, err : db.Prepare(INSERT INTO userinfo(username, department, created) values(?,?,?)) checkErr(err) res, err : stmt.Exec(astaxie, software developement, time.Now().Format(2006-01-02)) checkErr(err) id, err : res.LastInsertId() checkErr(err) fmt.Println(id of last inserted row , id) // 更新 stmt, err db.Prepare(update userinfo set username? where uid?) checkErr(err) res, err stmt.Exec(astaxieupdate, id) checkErr(err) affect, err : res.RowsAffected() checkErr(err) fmt.Println(affect, row(s) changed) // 查询 rows, err : db.Query(SELECT * FROM userinfo) checkErr(err) for rows.Next() { var uid int var username, department, created string err rows.Scan(uid, username, department, created) checkErr(err) fmt.Printf(%3v | %6v | %8v | %6v\n, uid, username, department, created) } // 删除 stmt, err db.Prepare(delete from userinfo where uid?) checkErr(err) res, err stmt.Exec(id) checkErr(err) affect, err res.RowsAffected() checkErr(err) fmt.Println(affect, row(s) changed) } func checkErr(err error) { if err ! nil { panic(err) } }这个示例与你可能已经读过的第 5.2 节 MySQL 示例 几乎一模一样——正如原文档指出的唯一的区别是驱动注册名与sql.Open的连接方式驱动注册_ github.com/mattn/go-sqlite3MySQL 为_ github.com/go-sql-driver/mysql连接参数sql.Open(sqlite3, ./foo.db)——第二个参数不是主机地址而是数据库文件的本地路径文件不存在时 SQLite 会自动创建占位符两者都使用?注意这与 PostgreSQL 的$1风格不同可对照 PostgreSQL 小节 体会差异。各操作的关键返回值插入res.LastInsertId()返回自增主键uid用于拿到新插入行的标识更新/删除res.RowsAffected()返回受影响的行数用于判断操作是否真正生效查询通过rows.Next()迭代游标再用rows.Scan(uid, username, department, created)将每一列依次扫描进对应变量。扫描顺序必须与 SELECT 的列顺序一致。单行结果与rows.Next()的注意事项原文档特别强调了两点容易被新手忽略的细节当结果只有一行时可以用if代替for循环if rows.Next() { err rows.Scan(uid, username, department, created) checkErr(err) fmt.Println(uid) fmt.Println(username) fmt.Println(department) fmt.Println(created) }必须先调用rows.Next()才能用Scan取数——Next()负责把游标推进到第一条记录并准备数据跳过它直接Scan是取不到数据的。此外仓库英文版示例还在查询后显式调用了rows.Close()良好的资源释放习惯并在main开头用defer db.Close()保证数据库连接最终被关闭这些都属于值得在生产代码中坚持的实践。实战如何在本地跑通示例仓库为每个章节示例都提供了独立的可运行目录ch.5.3 的 readme 给出了完整的本地运行步骤安装 SQLite 3下载并安装 SQLite 3 命令行工具创建数据库文件执行sqlite3 foo.db创建名为foo的数据库导入建表语句在 sqlite 交互界面中执行.read schema.sql读取并执行 SQL 语句随后用.tables确认表已创建输出应为userinfo退出 sqlite执行.exit下载依赖运行go get安装github.com/mattn/go-sqlite3等远程依赖包运行程序执行go run main.go。整个过程中生成的foo.db就是一个完整的 SQLite 数据库文件这也再次印证了只需一个二进制文件即可创建、连接和操作数据库的嵌入式特性。事务处理避免并发锁与保证数据一致性第 5.3 节明确指出上面的示例演示了如何从数据库读取数据但真实 Web 应用不仅需要读更需要写。写入时应当使用事务transaction原因在于当多个 goroutine 同时访问数据库时SQLite 的数据库文件可能会被锁定locked而锁竞争对 Web 应用是不可接受的使用事务可以有效保证数据库操作要么全部成功、要么全部失败的原子性从而避免大量潜在问题。仓库英文版给出了一个典型的事务示例先Prepare一条更新语句再开启事务并执行trashSQL, err : database.Prepare(update task set is_deletedY,last_modified_atdatetime() where id?) if err ! nil { fmt.Println(err) } tx, err : database.Begin() if err ! nil { fmt.Println(err) } _, err tx.Stmt(trashSQL).Exec(id) if err ! nil { fmt.Println(doing rollback) tx.Rollback() } else { tx.Commit() }这段代码的流程清晰体现了事务的标准三步法准备语句Prepare编译好 SQL占位符?留待执行时传入参数开启事务database.Begin()获得事务对象tx并将预编译语句绑定到事务上下文tx.Stmt(trashSQL)执行后二选一执行出错则tx.Rollback()回滚撤销本次操作对数据库的所有影响执行成功则tx.Commit()提交使变更永久生效。事务把预编译语句 原子提交/回滚组合在一起既提升了多次执行的性能语句只编译一次又为多并发场景提供了数据一致性保障。这是 Web 应用写入路径中应当养成的核心习惯。结语SQLite 在本书数据库章节中的定位从第 5.3 节的完整示例可以看出SQLite 与 MySQL、PostgreSQL 在 Go 中的用法高度同构更换驱动、调整sql.Open参数与占位符风格后database/sql标准接口之上的 CRUD 与事务代码可以平滑迁移。这正是指定database/sql标准接口的核心价值所在。若需要可视化地管理 SQLite 数据库文件官方文档同时推荐了 sqliteadmin 与 sqlitebrowser 等管理工具配合命令行工具即可完成表结构维护与数据浏览。继续深入学习可以按书中的章节顺序对照阅读 MySQL 与 PostgreSQL 小节体会三种数据库在 Go 驱动与 SQL 方言上的差异示例源码的完整运行方式可参考 ch.5.3 目录含 main.go、schema.sql 与 运行说明。赞分享文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载相关推荐Build Web Application with Golang 实战ch.5.3 使用 SQLite 与 database/sql 完成 CRUDBuild Web Application with Golang 实战ch.5.3 使用 SQLite 与 database/sql 完成 CRUD 导读文档教程在 Go 中嵌入 SQLite基于 database/sql 的零配置 CRUD 与事务实践Build Web Application with Golang 第 5.3 章在 Go 中嵌入 SQLite基于 database/sql 的零配置 CRUD 与事务实践Build Web Application with Golan文档教程Go Web 开发实战在 Build Web Application with Golang 中用对 SQLite驱动选型、CRUD 与事务处理Go Web 开发实战在 Build Web Application with Golang 中用对 SQLite驱动选型、CRUD 与事务处理 SQLi文档教程上一篇VeleroArk备份输出文件格式深度解析tar.gz 归档、ark-backup.json 与目录结构全指南下一篇Ark/Velero ark restore 命令族完全指南Kubernetes 集群资源恢复的 CLI 参考与源码解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表