探究 Go database/sql 包的设计模式

使用 Go 中的 SQL database 是容易的,只需下列这三步:

// 步骤 1:导入主要的 SQL 包
import "database/sql"

// 步骤 2:导入一个驱动包来明确要使用的 SQL 数据库
import _ "github.com/mattn/go-sqlite3"

// 步骤 3:用一个注册好的驱动名称来打开一个数据库
func main() {
  // ...
  db, err := sql.Open("sqlite3", "database.db")
  // ...
}

从这时候开始,对象 db 可以用相同的代码来查询和修改所有支持的 SQL 数据库。如果我们想从 SQLite 转到 PostgreSQL,类似的做法只需要导入另个一数据库的驱动包,以及在调用 sql.Open[1] 时传入另一个驱动名称。

在这篇博客里,我想简述一些 database/sql 背后的设计模式及架构。

主要的设计模式

database\sql 的架构受一个整体的设计模式制约。我尝试分析它可能是哪个经典的设计模式,然后策略模式看起来比较接近,尽管它不是那么的一致。如果你认为哪个设计模式更符合,请告诉我 [2]。

它看起来像这样:我们有一个想要呈现给用户的通用接口,并有一个针对每个数据库后端的实现。很显然,它听起来很像经典的接口+实现,Go在这方面特别擅长,它对接口的支持很强大。

所以第一个想法会是:创建一些用户会交互的 DB 接口,并且每个数据库后端都实现这些接口。听起来是不是很简单?

当然,但使用这个方法会有一些问题。记住的是 Go 建议接口尽量小,也就是实现较少的方法。这里我们需要较大一点的 DB 接口,而这导致了一些问题:

  1. 添加面向用户的能力是很困难的,因为他们可能需要对接口添加额外的方法。这个破坏了所有接口的实现,并且需要许多独立的项目去维护它们的代码。

  2. 让所有数据库后端封装相同的方法是困难的,因为如果用户想直接加方法到 DB 接口,是没有一个原生(不能直接修改接口的方法)的地方去添加的。它需要每个后端独立地实现,这是很浪费的,逻辑也是非常复杂的。

  3. 如果后端想增加可选的能力,对一个单一的接口来说,不为特定的后端采用类型转换,这是具有挑战性的。

因此,一个更好的想法应该像这样:从后端接口分离出面向用户的类型及方法。如图所示:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值