我最近一直在做一些编程,在尝试遵循Effective Go样式指南时,我有时会发现在命名包和接口以及结构时很难避免出现问题。
举个例子。
我可能有控制台包,其中 Console.go 文件包含控制台界面控制台结构和新增功能功能
//console/Console.go
package console
type Console interface {
Print(s String)
}
type console struct {
....
}
func (c *console) Print(s String){
....
}
func New() Console{
return &console{}
}
现在当我在某个地方使用它时,我到处都使用console.Console
类型。
当我在一个包中有两个或更多结构时,我最终会得到类似的东西
con := console.NewConsole()
我不介意拥有大多数扁平的包装结构,但我确实希望尽可能保持我的代码组织。我对IO.Reader和IO.Writer的想法很好,但是当包与事物相同但仍然需要分开时该怎么办。 (是的我知道给定的例子可能是Console.Writer,但让我们假装它完全不同)
所以我的问题是: 这种口吃效应是我应该担心的吗? (即它是不好的形式?) 有没有人有任何避免它的提示?
答案 0 :(得分:10)
口吃类型名称通常很好 - 拥有foo.Foo
并不罕见,因为包foo
专用于定义类型Foo
。这绝对没有错。
你想要避免的是不必要的口吃;只需foo.NewFoo
只需foo.New
足够精确,或foo.FooBar
和foo.FooBaz
foo.Bar
和foo.Baz
同样适用
考虑标准库的html/template
,它定义了一个类型(template.Template
)和一个构造函数(template.New
)。
答案 1 :(得分:0)
我的经验是,除非你只想在一个包中使用一个结构,否则你不会使用New(),这在使用一个通用设计模型时不方便。
拥有许多软件包的风险也是循环导入,因为结构通常是相互引用的。当你只允许包中的一个结构时,你将非常限制自己。
顺便说一下,你有这个代码:func New()* Console 其中Console是struct console的接口。为什么不从构造函数返回* console,因为无论如何它都是它提供的,我的想法是func New()* console更好。