包内组织的Golang数据库层

时间:2019-06-19 17:29:18

标签: go code-design

我想听听Golang大师的一些建议。 想象一下,我有一个包含许多表的数据库层软件包,我应该为它们定义结构和函数。例如,我有一个名为“ MyObject”的表,并为其定义了一个结构。

type MyObject struct {
    RecID       int
    Name        string
}

与此表/结构相关的函数是否方便,我定义接收器是这样的:

func (o MyObject) AllMyObjects() ([]MyObject, error) {
    // retreive all MyObjects by query
}


func (o *MyObject) OneMyObjects() (MyObject, error) {
    // retreive one MyObject by query
}

通过这种方式,由于我的db包通过结构和函数变得更大,因此调用这样的方法看起来更干净,更容易(尽管我应该定义1条额外的行):

var myobject MyObject
var myobjects,err = myobject.AllMyObjects()

而不是直接在程序包级别调用函数(db是我的程序包的名称)

var myobjects,err = db.AllMyObjects()

这是组织代码的Go方式吗?或者您对此有其他建议吗?

3 个答案:

答案 0 :(得分:1)

如果考虑如何使用它,这是组织代码的奇怪方法。方法是其接收者类型的行为MyObject的工作是从数据库中检索其他MyObject吗?听起来不对。那应该是连接数据库的工作。那可以是包函数,也可以是包装数据库连接或数据库会话的对象。每种方法都可能是有效的方法,具体取决于您的应用程序,数据库和测试需求(由于无法模拟包功能,因此很难对其进行测试)。

例如,如果您的模型类型是Foo和Bar,则数据库包可能具有FooStore和BarStore类型,每种类型都有通过ID获得一个,获得全部,插入一个,更新一个等等的方法(无论每种类型都需要。)

保持数据库代码与数据模型的分离通常很重要,这样,与该模型一起使用的程序包也不必导入DBAL,这有助于分离关注点。

答案 1 :(得分:1)

我喜欢本约翰逊的方法https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1

想法是将域对象放在基本包中,然后将数据库/ nosql / redis /任何持久层包装为子包中的服务。当我这样做时,我会遇到这样的事情:

  • myobject.go(定义MyObbject结构和MyObjectService接口,可能包含“获取,更新”之类的内容)
  • mysql /
    • myobject_service.go(为MySQL持久性实现MyObjectService)
  • redis /
    • myobject_service.go(redis的实现)

这使您可以在业务逻辑中传递MyObjectService,甚至不必关心持久性实际上是如何发生的。 mysql.MyObjectService具体结构倾向于保存诸如指向数据库连接的指针之类的东西。高速缓存程序包可能会将内容存储在内存中。等等

因此,换句话说,不要将您的结构奴役于数据库,而将自己锁定在特定的实现中。将业务代码逻辑与持久行为分开,并使用接口允许一致的模式访问持久数据。

答案 2 :(得分:0)

很好的问题。 通常,无论项目中使用哪种语言,我都会尝试应用MVC模式,在这种模式下,该数据库的方法应与模型分开。

enter image description here

我将创建另一个名为your_model_controller.go的文件,并将所有持久性责任赋予该文件

Introduction about MVC