深入探究 Go 語言中使用 SQLite 數據庫

引言

在軟件開發中,數據庫是管理和存儲數據的關鍵組件。SQLite 作為一款輕量級的嵌入式數據庫,因其零配置、高性能和易于集成等特性,成為眾多小型項目和嵌入式系統的理想選擇。而 Go 語言以其高效、簡潔的特點,為操作 SQLite 數據庫提供了強大的支持。本文將結合實際代碼,深入介紹如何在 Go 語言中使用 SQLite 數據庫,包括數據庫和表的創建、增刪改查操作以及操作的優化。

環境準備

在開始使用 Go 語言操作 SQLite 數據庫之前,我們需要安裝必要的庫。可以使用以下命令安裝github.com/mattn/go-sqlite3庫:

go get github.com/mattn/go-sqlite3

創建數據庫和表

創建數據庫

在 Go 語言中,使用database/sql包結合github.com/mattn/go-sqlite3驅動來操作 SQLite 數據庫。通過sql.Open函數可以打開或創建一個 SQLite 數據庫文件。以下是一個簡單的示例:

package mainimport ("database/sql""fmt""path/filepath"_ "github.com/mattn/go-sqlite3"
)const defDBPath = "./data"func initContDB() error {dbFile := filepath.Join(defDBPath, "test.db")var err errorgDB, err := sql.Open("sqlite3", dbFile)if err != nil {fmt.Println("open test db ", err)return err}fmt.Println("open test db ok")_, err = gDB.Query("SELECT COUNT(*) FROM sqlite_master")if err != nil {fmt.Println("test db query ", err)return err}return nil
}

在上述代碼中,sql.Open函數接受兩個參數:驅動名(這里是sqlite3)和數據庫文件的路徑。如果文件不存在,SQLite 會自動創建該文件。

創建表

在創建數據庫之后,我們需要創建表來存儲數據。可以使用Exec方法執行 SQL 語句來創建表。為了避免重復創建表,我們可以先檢查表是否已經存在。以下是創建表的示例代碼:

func existTable(db *sql.DB, tbl string) bool {stmt, err := db.Prepare("SELECT COUNT(*) FROM sqlite_master where tbl_name=?")if err != nil {fmt.Println(err)return false}defer stmt.Close()row := stmt.QueryRow(tbl)if row == nil {return false}var val introw.Scan(&val)if val == 0 {return false}return true
}func createTable() {if existTable(gDB, "t_cont_info") {return}tbl := `CREATE TABLE [t_cont_info]([name] VARCHAR PRIMARY KEY NOT NULL UNIQUE, [ver] VARCHAR, [image] VARCHAR NOT NULL, [cmd] INT(2) NOT NULL, [opt_cmd] INT(2) NOT NULL, [cpus] INT(2) NOT NULL, [cpu_threshold] INT(4) NOT NULL, [memory] INT(4) NOT NULL, [mem_threshold] INT(4) NOT NULL, [store_cap] INT(4) NOT NULL, [store_threshold] INT(4) NOT NULL, [ip] VARCHAR, [create_time] VARCHAR, [start_time] VARCHAR, [runtimes] BIGINT, [backup_path] VARCHAR,[opt_time] VARCHAR);`_, err := gDB.Exec(tbl)if err != nil {fmt.Println(err)return}fmt.Println("creatTable t_cont_info")
}

在上述代碼中,existTable函數用于檢查指定的表是否存在。createTable函數根據檢查結果決定是否創建t_cont_info表。

增刪改查操作

插入數據

插入數據可以使用PrepareExec方法。以下是插入的示例代碼:

func insertWarnMsg(name, msg string) error {stmt, err := gWarnDB.Prepare(`INSERT INTO t_cont_info([name], [msg], [opt_time]) VALUES (?,?,?)`)if err != nil {fmt.Println(err)return err}_, err = stmt.Exec(name, msg, getLocalTime())if err != nil {stmt.Close()fmt.Println(err)return err}stmt.Close()checkWarnLimit(name)return nil
}

在上述代碼中,Prepare方法用于準備 SQL 語句,Exec方法用于執行插入操作。

更新數據

更新數據的操作與插入數據類似,同樣使用PrepareExec方法。以下是更新的示例代碼:

func updContInfo(ct ContItem) {smt, err := gDB.Prepare("SELECT [name] FROM t_cont_info WHERE name=?")if err != nil {fmt.Println(err)return}defer smt.Close()upd := falserow := smt.QueryRow(ct.Name)if row != nil {var name stringerr = row.Scan(&name)if err != nil {} else if name == ct.Name {upd = true}}if upd {sqlCmd := `UPDATE t_cont_info SET [ver]=?, [image]=?, [cmd]=?, [opt_cmd]=?, [cpus]=?, [cpu_threshold]=?, [memory]=?, [mem_threshold]=?, [store_cap]=?, [store_threshold]=?, [ip]=?, [create_time]=?, [start_time]=?, [runtimes]=?, [backup_path]=?, [opt_time]=? WHERE [name]=?`stmt, err := gDB.Prepare(sqlCmd)if err != nil {fmt.Println(err, ", sql: ", sqlCmd)return}defer stmt.Close()_, err = stmt.Exec(ct.Ver, ct.Img, ct.Cmd, ct.OptCmd, ct.CPUs, ct.CPUThreshold,ct.Memory, ct.MemThreshold, ct.StoreCap, ct.StoreThreshold, ct.IP, ct.CreateTime,ct.StartTime, ct.RunTimes, ct.BackupPath, getLocalTime(), ct.Name)if err != nil {fmt.Println(err)return}} else {stmt, err := gDB.Prepare(`INSERT INTO t_cont_info([name] , [ver], [image], [cmd], [opt_cmd], [cpus], [cpu_threshold], [memory], [mem_threshold], [store_cap], [store_threshold], [ip], [create_time], [start_time], [runtimes], [backup_path], [opt_time]) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`)if err != nil {fmt.Println(err)return}defer stmt.Close()_, err = stmt.Exec(ct.Name, ct.Ver, ct.Img, ct.Cmd, ct.OptCmd, ct.CPUs, ct.CPUThreshold,ct.Memory, ct.MemThreshold, ct.StoreCap, ct.StoreThreshold, ct.IP, ct.CreateTime,ct.StartTime, ct.RunTimes, ct.BackupPath, getLocalTime())if err != nil {fmt.Println(err)return}}
}

在上述代碼中,首先檢查數據是否存在,如果存在則更新數據,否則插入新數據。

刪除數據

刪除數據可以使用PrepareExec方法執行DELETE語句。以下是刪除的示例代碼:

func deleteContItem(name string) {del := func(tbl, name string) {stmt, err := gDB.Prepare(fmt.Sprintf("DELETE FROM %s WHERE [name]=?", tbl))if err != nil {fmt.Println(err)return}defer stmt.Close()_, err = stmt.Exec(name)if err != nil {fmt.Println(err)return}}del("t_cont_info", name)del("t_cont_res_map", name)fmt.Println("deleteContItem: ", name)
}

在上述代碼中,定義了一個匿名函數del來執行刪除操作,分別刪除t_cont_infot_cont_res_map表中指定名稱的數據。

查詢數據

查詢數據可以使用Query方法執行SELECT語句,并使用Scan方法將結果掃描到變量中。以下是查詢所有數據的示例代碼:

func loadFromDB() (lst []ContItem, err error) {rows, err := gDB.Query(`SELECT [name] , [ver], [image], [cmd], [opt_cmd], [cpus], [cpu_threshold], [memory], [mem_threshold], [store_cap], [store_threshold], [ip], [create_time], [start_time], [runtimes], [backup_path] FROM t_cont_info`)if err != nil {fmt.Println(err)return}defer rows.Close()for rows.Next() {var ct ContItemrows.Scan(&ct.Name, &ct.Ver, &ct.Img, &ct.Cmd, &ct.OptCmd, &ct.CPUs, &ct.CPUThreshold,&ct.Memory, &ct.MemThreshold, &ct.StoreCap, &ct.StoreThreshold, &ct.IP,&ct.CreateTime, &ct.StartTime, &ct.RunTimes, &ct.BackupPath)ct.DevMapList, _ = loadContResMap(ct.Name, CONT_RES_DEV)ct.VolMapList, _ = loadContResMap(ct.Name, CONT_RES_VOL)ct.PortMapList, _ = loadContResMap(ct.Name, CONT_RES_PORT)lst = append(lst, ct)fmt.Println("loadFromDB: ", ct)}return
}

在上述代碼中,Query方法返回一個Rows對象,通過Next方法遍歷結果集,并使用Scan方法將數據存儲到ContItem結構體中。

操作優化

批量操作

在進行大量數據的插入或更新操作時,可以使用事務來提高性能。事務可以將多個操作合并為一個原子操作,減少數據庫的開銷。以下是一個使用事務進行批量插入的示例代碼:

func batchInsert(data []interface{}) error {tx, err := gDB.Begin()if err != nil {return err}stmt, err := tx.Prepare("INSERT INTO table_name (column1, column2) VALUES (?,?)")if err != nil {tx.Rollback()return err}defer stmt.Close()for _, item := range data {_, err = stmt.Exec(item.Value1, item.Value2)if err != nil {tx.Rollback()return err}}return tx.Commit()
}

在上述代碼中,Begin方法開始一個事務,Prepare方法準備 SQL 語句,Exec方法執行插入操作,最后使用Commit方法提交事務。如果發生錯誤,使用Rollback方法回滾事務。

索引優化

為經常用于查詢條件的列創建索引可以提高查詢性能。例如,在t_cont_info表中,如果經常根據name列進行查詢,可以為name列創建索引:

func createIndex() {_, err := gDB.Exec("CREATE INDEX idx_name ON t_cont_info (name)")if err != nil {fmt.Println(err)return}fmt.Println("create index idx_name")
}

在上述代碼中,使用CREATE INDEX語句為name列創建索引。

總結

本文深入介紹了如何在 Go 語言中使用 SQLite 數據庫,包括數據庫和表的創建、增刪改查操作以及操作的優化。通過使用database/sql包和github.com/mattn/go-sqlite3驅動,我們可以方便地操作 SQLite 數據庫。在實際開發中,根據具體需求選擇合適的操作方法和優化策略,可以提高程序的性能和穩定性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84861.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84861.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84861.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Portable Computer Power Adapter

Portable Computer Power Adapter 筆記本電源適配器,將220伏特的交流電轉化直流電 現在的適配器真的體積之大,讓我無法理解,本來便攜計算機為了方便減少體積重量,現在都倒反天罡了。讓我無法理解設計師是怎么干出來的。這玩意有2…

Uniapp 網絡請求封裝專題

目錄 一、前言 二、uniapp官方文檔 三、舉例演示 3.1 使用說明 3.2 Content-Type 3.2.1 ??基本概念 ??3.2.2 核心作用 3.2.3 常見 Content-Type 類型及使用場景 1)文本類 a)text/plain???? b)text/html?? 2&#xf…

2025年滲透測試面試題總結-2025年HW(護網面試) 07(題目+回答)

安全領域各種資源,學習文檔,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具,歡迎關注。 目錄 2025年HW(護網面試) 07 一、OWASP Top 10 2023核心漏洞 二、XSS竊取Cookie全流程 三、滲透測試五階段模型…

Seata分布式事務解決框架

Seata(Simple Extensible Autonomous Transaction Architecture)是一個開源的分布式事務解決方案,旨在幫助開發者更容易地在微服務架構中解決分布式事務問題。 你可以把它理解為一個工具箱,專門用來處理微服務之間操作的一致性。…

舊物回收小程序開發:開啟綠色生活新方式

在環保理念日益深入人心的今天,每一件舊物都承載著資源再生的無限可能。我們精心打造的舊物回收小程序,宛如一把神奇的鑰匙,為你開啟綠色生活新方式! 想象一下,家中堆積如山的舊衣物、閑置的電子產品、廢棄的書籍雜志…

STM32 串口通信②:藍牙模塊HC-05控制單片機

一 前言 上一篇我們已經成功實現單片機和電腦的連接,接下來,我們學習一個有趣的板塊,HC-05藍牙模塊,這個藍牙模塊,我們就要建立手機和單片機的通訊啦,還是比較有趣的一個過程,大家可以跟著多操作…

【Verilog】Verilator的TestBench該用C++還是SystemC

Verilator的Testbench(測試平臺)主要使用 C 或 SystemC 來編寫。這是由Verilator的工作原理決定的:它將你的Verilog/SystemVerilog設計轉換成一個C類,因此你需要一個C環境來實例化和驅動這個類。 下面詳細說明這兩種方式以及如何…

71-Oracle Undo與Flashback管理(Guarantee設置)深度解析

小伙伴們有沒有在操作undo表空間、Flashback管理,時間保留設置,總有些配置需要提前預置好,否則閃回查詢和表的時候出現報錯。 需短期恢復(秒級~小時)直接上UNDO_RETENTION同時啟用RETENTION GUARANTEE,Und…

單片機——浮點數轉換4位數碼管顯示

浮點數轉換4位數碼管顯示 static char buffer[5]; int DecimalPlace 0; #define HideChar h void DisplayFloatOn4LED(float value) {long integer roundf(value );if (integer > 9999) //4位{integer 9999;snprintf(buffer, sizeof(buffer), "%4ld", integer…

金融行業B端系統布局實戰:風險管控與數據可視化的定制方案

摘要 在金融行業,一次小小的數據泄露可能引發千萬級資金損失,一次錯誤的風險評估或許讓企業陷入危機。傳統 B 端系統布局在應對復雜多變的金融業務時,常出現風險預警滯后、數據雜亂無章的情況,讓從業者如履薄冰。如何才能在瞬息萬…

融合LSTM與自注意力機制的多步光伏功率預測新模型解析

這篇論文《Improved multistep ahead photovoltaic power prediction model based on LSTM and self-attention with weather forecast data》(2024, Applied Energy)聚焦在 多步光伏功率預測 中,如何結合 LSTM 與自注意力機制(se…

Blazor-內置輸入組件

封裝的輸入組件 InputCheckbox:表示復選框。InputDate:表示類型為 date 的日期選擇框。InputFile:表示文件上傳。InputNumber:表示數字框。InputRadio:表示單選按鈕。InputRadioGroup:表示單選按鈕組。Inpu…

Qt源碼分析: QChildEvent

本文記錄QChildEvent事件相關代碼分析。 注1:限于筆者研究水平,難免有表述不當,歡迎批評指正。 注2:博文會不定期更新,敬請關注。 一、QChildEvent的發送 分析QObject::setParent代碼,當修改父對象時&…

《Whisper :說明書 》

[論文] [模型卡] [Colab 示例] Whisper 是一種通用的語音識別模型。它基于各種音頻的大型數據集進行訓練,也是一種多任務模型,可以執行多語言語音識別、語音翻譯和語言識別。 方法 Transformer 序列到序列模型針對各種語音處理任務進行訓練,…

回溯----8.N皇后

題目鏈接 /** 將n個棋子放在n*n的棋盤上,不同列,不同行,不同斜線 大致執行流程: 首先選取第一行第一格放置第一個棋子,再從第二行第一個位置開始選取合法的位置(不同行不同列不同斜線)放置棋子,重復上述流程迭代行數, 直到放置n個棋子。 若放置途中出現無合法位置的情況,回溯將…

微機電子拉伸試驗機

對于不同材料的試樣,由于其化學成分及組織的不同,在拉伸過程中會體現 出不同的物理現象及力學性質。西安力創(LETRY)公司專業制造WDL/WDW系列微機控制電子萬能試驗機,主要適用于金屬板材、棒材、管材、金屬絲、金屬箔、…

【數據結構與算法】數據結構核心概念系統梳理

第一章 緒論:基礎概念體系 ??算法:問題求解步驟的描述。 ??非遞歸的算法效率更高。 1.1 邏輯結構 vs 存儲結構 維度邏輯結構存儲結構(物理結構)定義數據元素之間的邏輯關系數據結構在計算機中的實現方式分類線性/樹形/圖/集合順序/鏈式/索引/散列獨立性獨立于存儲結構…

73頁PPT | 大數據平臺規劃與數據價值挖掘應用咨詢項目解決方案

推薦摘要:在數字化浪潮中,企業數據量呈幾何級增長,卻常因缺乏科學規劃的大數據平臺,陷入數據孤島、處理效率低下的困境,難以充分挖掘數據價值。特推出大數據平臺規劃與數據價值挖掘應用咨詢項目解決方案,正…

gRPC 與 Protobuf 的深度集成 —— 從服務定義到多語言交互(Go + Java 示例)

在前幾篇文章中,我們已經掌握了 Protobuf 的基礎語法、高級特性和序列化反序列化操作。本篇文章將深入講解 gRPC 與 Protobuf 的集成,重點介紹如何通過 .proto 文件定義服務接口,并在 Go 和 Java 中實現 gRPC 服務與客戶端的完整交互流程。我…

可信計算的基石:TPM技術深度解析與應用實踐

可信計算的基石:TPM技術深度解析與應用實踐 引言:數字世界的"信任之錨" 在數據泄露事件頻發的時代,傳統軟件級安全防護已力不從心。TPM(可信平臺模塊)作為硬件級安全解決方案,正成為現代計算設…