更换GORM默认SQLite驱动出现的问题解决分析

 更新时间:2024年02月01日 14:12:12   作者:sample SK 刹客网络科技资讯  
这篇文章主要为大家介绍了更换GORM默认SQLite驱动出现的问题解决分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

GORM简介

GORM 是 Go 语言中最受欢迎的 ORM 库之一,它提供了强大的功能和简洁的 API,让数据库操作变得更加简单和易维护。本文将详细介绍 GORM 的常见用法,包括数据库连接、模型定义、CRUD、事务管理等方面,帮助大家快速上手使用 GORM 进行 Web 后端开发。

安装

通过如下命令安装 GORM:

$ go get -u gorm.io/gorm

你也许见过使用 go get -u github.com/jinzhu/gorm 命令来安装 GORM,这个是老版本 v1,现已过时,不建议使用。新版本 v2 已经迁移至 github.com/go-gorm/gorm 仓库下。

快速开始GORM使用

如下示例代码带你快速上手 GORM 的使用:

package main
import (
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)
// Product 定义结构体用来映射数据库表
type Product struct {
    gorm.Model
    Code  string
    Price uint
}
func main() {
    // 建立数据库连接
    db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }
    // 迁移表结构
    db.AutoMigrate(&Product{})
    // 增加数据
    db.Create(&Product{Code: "D42", Price: 100})
    // 查找数据
    var product Product
    db.First(&product, 1)                 // find product with integer primary key
    db.First(&product, "code = ?", "D42") // find product with code D42
    // 更新数据 - update product's price to 200
    db.Model(&product).Update("Price", 200)
    // 更新数据 - update multiple fields
    db.Model(&product).Updates(Product{Price: 200, Code: "F42"}) // non-zero fields
    db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})
    // 删除数据 - delete product
    db.Delete(&product, 1)
}

提示:这里使用了 SQLite 数据库驱动,需要通过 go get -u gorm.io/driver/sqlite 命令安装。

将以上代码保存在 main.go 中并执行。

$ go run main.go

执行完成后,我们将在当前目录下得到 test.db SQLite 数据库文件。

① 进入 SQLite 命令行。

② 查看已存在的数据库表。

③ 设置稍后查询表数据时的输出模式为按列左对齐。

④ 查询表中存在的数据。

有过使用 ORM 框架经验的同学,以上代码即使我不进行讲解也能看懂个大概。

这段示例代码基本能够概括 GORM 框架使用套路:

  • 定义结构体映射表结构:Product 结构体在 GORM 中称作「模型」,一个模型对应一张数据库表,一个结构体实例对象对应一条数据库表记录。
  • 连接数据库:GORM 使用 gorm.Open 方法与数据库建立连接,连接建立好后,才能对数据库进行 CRUD 操作。
  • 自动迁移表结构:调用 db.AutoMigrate 方法能够自动完成在数据库中创建 Product 结构体所映射的数据库表,并且,当 Product 结构体字段有变更,再次执行迁移代码,GORM 会自动对表结构进行调整,非常方便。不过,我不推荐在生产环境项目中使用此功能。因为数据库表操作都是高风险操作,一定要经过多人 Review 并审核通过,才能执行操作。GORM 自动迁移功能虽然理论上不会出现问题,但线上操作谨慎为妙,个人认为只有在小项目或数据不那么重要的项目中使用比较合适。
  • CRUD 操作:迁移好数据库后,就有了数据库表,可以进行 CRUD 操作了。

更换第三方SQLite驱动解决

最近在开发一个程序时用到GORM来操作SQLite数据库,GORM默认使用gorm.io/driver/sqlite这个库作为SQLite驱动,该库用CGO实现,在使用过程中遇到一些问题,最后更换第三方SQLite驱动解决。

问题

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

[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支持即可:

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

于是将官方的驱动:

import (
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)

更换为:

import (
    "github.com/glebarez/sqlite"
    "gorm.io/gorm"
)

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

代价

  • glebarez/sqlite性能不及官方驱动,但牺牲少部分性能来换取方便个人觉得还是值得的,如果没有跨平台需求,使用官方默认驱动即可
  • 静态编译打包后的文件体积明显增加

以上就是更换GORM默认SQLite驱动出现的问题解决分析的详细内容,更多关于更换GORM默认SQLite驱动的资料请关注脚本之家其它相关文章!

相关文章

  • 试了下Golang实现try catch的方法

    试了下Golang实现try catch的方法

    虽然在使用Golang的时候发现没有try catch这种错误处理机制但是想一想golang作为一门优雅的语言,似乎也是情理之中。那么够怎么捕获异常呢,本文就来介绍一下
    2021-07-07
  • 详解Golang如何实现支持随机删除元素的堆

    详解Golang如何实现支持随机删除元素的堆

    堆是一种非常常用的数据结构,它能够支持在O(1)的时间复杂度获取到最大值(或最小值)。本文主要介绍了如何实现支持O(log(n))随机删除元素的堆,需要的可以参考一下
    2022-09-09
  • golang实现简单的udp协议服务端与客户端示例

    golang实现简单的udp协议服务端与客户端示例

    这篇文章主要介绍了golang实现简单的udp协议服务端与客户端,结合实例形式分析了基于UDP协议的数据传输相关实现技巧,需要的朋友可以参考下
    2016-07-07
  • Go语言驱动低代码应用引擎工具Yao开发管理系统

    Go语言驱动低代码应用引擎工具Yao开发管理系统

    这篇文章主要为大家介绍了Go语言驱动低代码应用引擎工具Yao开发管理系统使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • GO将mysql 中 decimal 数据类型映射到 protobuf的操作方法

    GO将mysql 中 decimal 数据类型映射到 protobuf的操作方法

    这篇文章主要介绍了go如何优雅地将 mysql 中 decimal 数据类型映射到 protobuf,本文主要展示一下在 protobuf中 float与double的一个区别,结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • Golang 性能基准测试(benchmark)详解

    Golang 性能基准测试(benchmark)详解

    Golang性能基准测试可以帮助开发人员比较不同的实现方式对性能的影响,以便优化程序,本文就来讲解一下如何使用Golang的性能基准测试功能,需要的朋友可以参考下
    2023-06-06
  • Golang中的time.Duration类型用法说明

    Golang中的time.Duration类型用法说明

    这篇文章主要介绍了Golang中的time.Duration类型用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 浅析Go汇编语法和MatrixOne使用介绍

    浅析Go汇编语法和MatrixOne使用介绍

    MatrixOne由Go语言所开发是一个新一代超融合异构数据库,致力于打造单一架构处理TP、AP、流计算等多种负载的极简大数据引擎,今天通过本文给大家介绍Go汇编语法和MatrixOne使用,感兴趣的朋友一起看看吧
    2022-04-04
  • Go中的 panic / recover 简介与实践记录

    Go中的 panic / recover 简介与实践记录

    这篇文章主要介绍了Go中的 panic / recover 简介与实践,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • Golang 实现 Redis系列(六)如何实现 pipeline 模式的 redis 客户端

    Golang 实现 Redis系列(六)如何实现 pipeline 模式的 redis 客户端

    pipeline 模式的 redis 客户端需要有两个后台协程负责 tcp 通信,调用方通过 channel 向后台协程发送指令,并阻塞等待直到收到响应,本文是使用 golang 实现 redis 系列的第六篇, 将介绍如何实现一个 Pipeline 模式的 Redis 客户端。
    2021-07-07

最新评论