golang的sqlite驱动不使用cgo实现 更换gorm默认的SQLite驱动

golang的sqlite驱动不使用cgo实现 更换gorm默认的SQLite驱动

最近在开发一个边缘物联网程序时使用Golang开发,用到GORM来操作SQLite数据库,GORM默认使用gorm.io/driver/sqlite这个库作为SQLite驱动,该库用CGO实现,在使用过程中遇到一些问题,编译好二进制程序放到资源受限的设备中运行,报错如下;最后更换第三方SQLite驱动解决。

github.com/mattn/go-sqlite3 这个库现在在 go 项目当中,引用最多,应用最广;俨然成为这一方面的标准,但有一个最大的问题就是,这是一个 C 语言实现的库,如果要应用这个库,那么你的环境就需要解决这个 CGO 依赖。

报错如下,正是因为GORM官方SQLite驱动使用CGO实现,因此我在使用过程中遇到以下错误:

shell 复制代码
[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驱动使用了CGO实现,需要在CGO环境下才能工作。

那么解决方法也很简单,只需要修改CGO_ENABLED这个环境变量启用CGO支持即可:

shell 复制代码
go env -w CGO_ENABLED=1

启用CGO后,编译的是动态链库的二进制文件,那么你一旦更换平台,比如将程序放到Windows下运行,可能因为缺少相关的一些动态链库(比如:SQLite)从而无法运行,为了保持编译的二进制文件能够无动态依赖的情况下正常运行,因此不得不考虑静态编译,所以就和GORM SQLite驱动产生了冲突。

很多瘦小设备,弱设备里的系统,没有相关依赖库和驱动,也很难安装相关的驱动,此时不得不考虑使用不依赖任何三方的驱动情况下运行程序。

解决方案-更换GORM默认的SQLite驱动

在GORM官方的Issues发现也有人反馈此类问题,于是顺藤摸瓜,找到了github.com/glebarez/sqlite这个库,该库使用纯go实现,不依赖CGO,地址是:https://github.com/glebarez/sqlite

使用如下驱动

golang 复制代码
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.DB

func SqliteInit() {
	var err error
	SqliteDb, 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)

	// 空闲状态下的最大连接数,默认的最大空闲连接数为2
	SqliteDb.DB().SetMaxIdleConns(10)
	// 最大打开连接数, 默认值为0(无限制)
	SqliteDb.DB().SetMaxOpenConns(50)
	// 不要复数表名
	SqliteDb.SingularTable(true)

	// 自动迁移模型(创建表)
	//SqliteDb.AutoMigrate()
}

func SqliteClose() {
	//关闭
	SqliteDb.Close()
}

这样就可以在不依赖CGO的情况下编译出静态二进制文件,从而解决跨平台依赖动态链库的问题。

代价

glebarez/sqlite性能不及官方驱动,但牺牲少部分性能来换取方便个人觉得还是值得的,如果没有跨平台需求,使用官方默认驱动即可

静态编译打包后的文件体积明显增加

参考链接:

https://blog.xiaoz.org/archives/18195

https://wiki.eryajf.net/pages/74da0a/#前言

https://yoby123.cn/2021/06/15/20210615-sqlite.html

相关推荐
资深web全栈开发13 小时前
并查集(Union-Find)套路详解
leetcode·golang·并查集·unionfind
moxiaoran575315 小时前
Go语言的递归函数
开发语言·后端·golang
朝花不迟暮15 小时前
Go基础-闭包
android·开发语言·golang
西京刀客17 小时前
go语言-切片排序之sort.Slice 和 sort.SliceStable 的区别(数据库分页、内存分页场景注意点)
后端·golang·sort·数据库分页·内存分页
黄昏单车18 小时前
golang语言基础到进阶学习笔记
笔记·golang·go
moxiaoran57531 天前
Go语言结构体
开发语言·后端·golang
Tony Bai1 天前
Cloudflare 2025 年度报告发布——Go 语言再次“屠榜”API 领域,AI 流量激增!
开发语言·人工智能·后端·golang
小徐Chao努力2 天前
Go语言核心知识点底层原理教程【变量、类型与常量】
开发语言·后端·golang
锥锋骚年2 天前
go语言异常处理方案
开发语言·后端·golang
moxiaoran57532 天前
Go语言的map
开发语言·后端·golang