Go 语言如何进行数据库操作:database/sql 与 GORM 对比

Created time
Mar 4, 2023 03:19 AM
date
Feb 22, 2023
slug
golang-sql
status
Published
summary
tags
编程
type
Post
Go 语言程序操作数据库主要有两种方式
  • 使用 ORM,本文以 GORM 作为例子

GORM

使用 GORM 似乎是最流行的方式,无论是各类新手教程还是我在工作中见到的所有项目都使用了这个库。

示例代码

定义一个 Go 结构体,对应一张数据库表。约定优于配置,GORM 有默认的自动行为。在业务代码中,通过 GORM 接口进行数据库操作。

项目代码

来看一个项目内的源代码例子:article.go
这个项目是一本 Go 语言教程书的教学项目,程序功能简单易懂。如果你有更好的例子,欢迎在评论区补充。
一个我不满意的小问题:开发者已经定义了一个 Go 结构体来对应数据库里的一张表,但是在某些情况,还要用字符串来指定列。

优点

  • 如果场景简单(大部分内容是单张表的查询创建、删除、更新等等),使用 GORM 的逻辑代码非常直观。举个例子:如果团队中的初级工程师想要添加一张表,并且编写代码执行增删改查操作,他/她并不需要了解细节。其次,GORM 的自动迁移功能非常好用。
  • 大多数业务系统的内部实现,就是上述的简单场景。更何况,很多业务代码会在数据库列内存储大量 json 序列化文本 🤮 让一张表包含更多维度的信息。
  • 几乎完全屏蔽数据库细节。例如:从 MySQL 迁移至 PostgreSQL,业务代码改动的工作量也许并不多。 然而,实际上绝大多数的业务不可能改数据库。
  • 更高级的场景也许还有很多好处,GORM 的功能非常丰富,在日常工作中我也只使用了一小部分。关于安全以及性能方面我的了解不多,欢迎读者补充。

缺点

  • 额外的学习成本。如果你是一位使用其他语言的程序员,可能你已经可以熟练使用 SQL 进行数据库操作,但是使用 GORM 仍然需要学习 GORM 库提供的 API 和 SQL 语句的对应关系。
  • 复杂场景,例如联表查询、事务等功能,使用 GORM 开发的代码也会相应复杂,并不直观。开发者首先需要思考最终执行的 SQL 语句,再去编写调用 GORM 的业务代码,最后再检查这些代码是否真的按照自己的想法执行了正确的 SQL 语句。如果能直接执行 SQL,也许是更好的选择?

其他

database/sql

databse/sql 位于 Go 语言标准库,实际上 GORM 也会在内部调用它。

使用方法

  • 官方库只提供了接口,在 Go 程序中连接不同类型的数据库需要使用不同的 driver。
  • 手写 SQL 语句,手动解析(Scan)返回的字符串文本

优点

  • 直观,开发者可以清楚地了解被执行的 SQL 语句是什么。

缺点

  • 对于简单场景,手动写 SQL 语句再手动解析、赋值,代码相比使用 ORM 更繁琐。
  • 少了一些辅助功能,例如:GORM 默认会打印慢查询语句以及它的执行时间。如果使用 database/sql 库,这个功能没有简单方便的实现方式。
  • 不同数据库 driver 的实现方式不同,有的 driver 并不支持全部功能,可能导致开发体验较差。例如:lib/pq(PostgreSQL 的 driver)并不支持用 "?" 作为参数占位符,只支持 "$1" "$2" 的形式,在拼接复杂 SQL 语句时代码非常繁琐。而 GORM 的处理方式不会造成这个问题:docs/sql_builder

其他

使用 databse/sql 会有 SQL 注入的问题吗?
  • TLDR:不要直接拼接用户输入的字符串来生成 SQL 语句,使用参数占位符来传递值可以避免 SQL 注入。

总结

使用 ORM 还是使用 database/sql 库,哪个更好?从我的经验来看这个问题没有一个明确的答案,具体选择要根据实际情况。各有优劣,而现实常常没有选择权。
GORM 无法避开,你大概率会在工作中用到。推荐有时间的朋友尝试一下直接使用 database/sql 库,体验一下“简练”的代码。

© nilh2a2 2024