合肥做網(wǎng)站多少錢資源網(wǎng)
golang的sqlite驅(qū)動不使用cgo實現(xiàn) 更換gorm默認的SQLite驅(qū)動
最近在開發(fā)一個邊緣物聯(lián)網(wǎng)程序時使用Golang開發(fā),用到GORM來操作SQLite數(shù)據(jù)庫,GORM默認使用gorm.io/driver/sqlite這個庫作為SQLite驅(qū)動,該庫用CGO實現(xiàn),在使用過程中遇到一些問題,編譯好二進制程序放到資源受限的設備中運行,報錯如下;最后更換第三方SQLite驅(qū)動解決。
github.com/mattn/go-sqlite3 這個庫現(xiàn)在在 go 項目當中,引用最多,應用最廣;儼然成為這一方面的標準,但有一個最大的問題就是,這是一個 C 語言實現(xiàn)的庫,如果要應用這個庫,那么你的環(huán)境就需要解決這個 CGO 依賴。
報錯如下,正是因為GORM官方SQLite驅(qū)動使用CGO實現(xiàn),因此我在使用過程中遇到以下錯誤:
[error] failed to initialize database, got error Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub panic: Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub
大致意思是GORM SQLite驅(qū)動使用了CGO實現(xiàn),需要在CGO環(huán)境下才能工作。
那么解決方法也很簡單,只需要修改CGO_ENABLED這個環(huán)境變量啟用CGO支持即可:
go env -w CGO_ENABLED=1
啟用CGO后,編譯的是動態(tài)鏈庫的二進制文件,那么你一旦更換平臺,比如將程序放到Windows下運行,可能因為缺少相關的一些動態(tài)鏈庫(比如:SQLite)從而無法運行,為了保持編譯的二進制文件能夠無動態(tài)依賴的情況下正常運行,因此不得不考慮靜態(tài)編譯,所以就和GORM SQLite驅(qū)動產(chǎn)生了沖突。
很多瘦小設備,弱設備里的系統(tǒng),沒有相關依賴庫和驅(qū)動,也很難安裝相關的驅(qū)動,此時不得不考慮使用不依賴任何三方的驅(qū)動情況下運行程序。
解決方案-更換GORM默認的SQLite驅(qū)動
在GORM官方的Issues發(fā)現(xiàn)也有人反饋此類問題,于是順藤摸瓜,找到了github.com/glebarez/sqlite這個庫,該庫使用純go實現(xiàn),不依賴CGO,地址是:https://github.com/glebarez/sqlite
使用如下驅(qū)動
import ("fmt"_ "github.com/glebarez/sqlite""github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/sqlite"
)const (dbDriverName = "sqlite"dbName = "iot.db"
)var SqliteDb *gorm.DBfunc SqliteInit() {var err errorSqliteDb, err = gorm.Open(dbDriverName, "./"+dbName)if err != nil {fmt.Printf("connect DB failed, err:%v\n", err)return}fmt.Println("connect DB success")// 打印 SQL 語句SqliteDb.LogMode(true)// 空閑狀態(tài)下的最大連接數(shù),默認的最大空閑連接數(shù)為2SqliteDb.DB().SetMaxIdleConns(10)// 最大打開連接數(shù), 默認值為0(無限制)SqliteDb.DB().SetMaxOpenConns(50)// 不要復數(shù)表名SqliteDb.SingularTable(true)// 自動遷移模型(創(chuàng)建表)//SqliteDb.AutoMigrate()
}func SqliteClose() {//關閉SqliteDb.Close()
}
這樣就可以在不依賴CGO的情況下編譯出靜態(tài)二進制文件,從而解決跨平臺依賴動態(tài)鏈庫的問題。
代價
glebarez/sqlite性能不及官方驅(qū)動,但犧牲少部分性能來換取方便個人覺得還是值得的,如果沒有跨平臺需求,使用官方默認驅(qū)動即可
靜態(tài)編譯打包后的文件體積明顯增加
參考鏈接:
https://blog.xiaoz.org/archives/18195
https://wiki.eryajf.net/pages/74da0a/#%E5%89%8D%E8%A8%80
https://yoby123.cn/2021/06/15/20210615-sqlite.html