是否值得在结构中对方法进行分组:例如:
type UserManager struct {
DB *sql.DB
}
func (m UserManager) Insert (u User) error {...}
func (m UserManager) Delete (u User) error {...}
...或者它更简单,只支持单独的功能。
func InsertUser (u User, db *sql.DB) error {...}虽然第二种方法一开始看起来更简单,但在未来这种方式下,包中可能会有很多函数。我应该为每个域聚合创建单独的包吗?到目前为止,我看到的示例中只有model包。我主要从事面向对象语言的工作,所以这里需要一些关于go最佳实践的建议。
发布于 2017-02-19 02:24:14
你的第二个建议不是好的go代码!为什么?因为在最好的情况下,函数应该将接口作为输入。
所以InsertUser函数应该看起来像这样,它会把你的第一个建议和第二个建议结合起来:
type Inserter interface {
Insert(User)error
}
func InsertUser(i Inserter) error {...}在这种情况下,测试您的函数很容易,因为您可以很容易地模拟插入器。
发布于 2017-02-19 02:34:22
或者都不是--在我看来,这真的无关紧要,因为惯用的方法是使用接口来组织这些概念:
package user
type User ...
type Inserter interface { Insert(User) error }
type Deleter interface { Delete(User) error }
type Manager interface { Inserter, Deleter } // bloated interface本例中的User可能是一个具体的row类型,就像您的示例中一样,但也可以将其转换为不提及这些类型的接口。
如果您编写引用这些接口的函数,那么您可以使用embedding & promoted fields快速地粘合在一起。
在您的例子中,很明显,坚持第一种实现风格要简单得多:
type userManager struct { ... }
func (userManager) Insert(u User) error { ... }
func (userManager) Delete(u User) error { ... }userManager是一个私有类型,所以只要它满足公共接口,就可以不受关注地进行更改。
保持接口与实现的解耦使得缩小接口范围变得更容易,因此,您可以找出您真正需要哪些接口来完成任务,而不是只有一个“用户管理器”或其他东西。顺便说一句,这种方法有一个很好的特性,它非常适合object capability model,这有助于简化诸如基于角色的访问控制之类的事情。
https://stackoverflow.com/questions/42317700
复制相似问题