我想听听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方式吗?或者您对此有其他建议吗?
答案 0 :(得分:1)
如果考虑如何使用它,这是组织代码的奇怪方法。方法是其接收者类型的行为。 MyObject
的工作是从数据库中检索其他MyObject
吗?听起来不对。那应该是连接数据库的工作。那可以是包函数,也可以是包装数据库连接或数据库会话的对象。每种方法都可能是有效的方法,具体取决于您的应用程序,数据库和测试需求(由于无法模拟包功能,因此很难对其进行测试)。
例如,如果您的模型类型是Foo和Bar,则数据库包可能具有FooStore和BarStore类型,每种类型都有通过ID获得一个,获得全部,插入一个,更新一个等等的方法(无论每种类型都需要。)
保持数据库代码与数据模型的分离通常很重要,这样,与该模型一起使用的程序包也不必导入DBAL,这有助于分离关注点。
答案 1 :(得分:1)
我喜欢本约翰逊的方法https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1
想法是将域对象放在基本包中,然后将数据库/ nosql / redis /任何持久层包装为子包中的服务。当我这样做时,我会遇到这样的事情:
这使您可以在业务逻辑中传递MyObjectService,甚至不必关心持久性实际上是如何发生的。 mysql.MyObjectService具体结构倾向于保存诸如指向数据库连接的指针之类的东西。高速缓存程序包可能会将内容存储在内存中。等等
因此,换句话说,不要将您的结构奴役于数据库,而将自己锁定在特定的实现中。将业务代码逻辑与持久行为分开,并使用接口允许一致的模式访问持久数据。
答案 2 :(得分:0)
很好的问题。 通常,无论项目中使用哪种语言,我都会尝试应用MVC模式,在这种模式下,该数据库的方法应与模型分开。
我将创建另一个名为your_model_controller.go
的文件,并将所有持久性责任赋予该文件