英文:
Structuring go interfaces with subpackages
问题
我正在开发我的第一个真正的Go应用程序,并试图理清代码文件的结构。
我的代码的主要部分将是一些实现了共同接口的类型。
type Runner interface {
Run() string
}
它们将位于一个包中。由于接口实现的数量将非常大,我希望将它们(语义上)分成几个子包。
runner/
blue/
red/
Runner
的实现需要访问一些在应用程序的其他地方定义的接口(例如 Cache
和 Secret
)。这些接口目前在单独的包中定义和实现。我的计划是使用一个包含所有这些实用接口的 Config
结构,并将其传递给 Runner
的实现。
我不确定如何最好地处理这些子包以及在哪里放置 Config
和接口声明。
我的直觉做法是在 runner
包中同时定义 Config
结构和 Runner
接口,并且只从那里返回一个 []Runner
集合,但这违反了这个建议。
此外,所需的导入数量和可能遇到的禁止的循环引用的危险让我觉得,我的解决方案违反了最佳实践。
有没有建议如何改进我的代码结构?
是否建议添加一个包含所有接口定义和 Config
结构的 common
包?
英文:
I am developing my first real go application and am trying to wrap my hand around my codefiles should be structured.
The main part of my code is going to be a number of types which all implement a common interface.
type Runner interface {
Run() string
}
They are going to be in a package. As the number of the interface implementations is going to be very large I would like to split them (semantically) into a couple of subpackages.
runner/
blue/
red/
The Runner
implementation need access to a couple of other interfaces that are defined elsewhere in my application (e.g., Cache
and Secret
). Those are currently defined & implemented in separate packages. My plan is to use a Config
struct, which contains all those utility interfaces and pass it to the Runner
implementations.
I am unsure how to best handle those subpackages and where to put the Config
and interface declarations.
My intuitive approach would be to define both the Config
struct and the Runner
interface in the runner
package and only return a []Runner
collection from there, but this violates this recommendation.
Also, the number of imports required and the danger of running into circular references which are prohibited gives me the feeling, that my solution is going against best practices.
Are there any suggestions how to improve my code structure?
Would adding a common
package which contains all my interface definitions and the Config
struct be advisable?
答案1
得分: 0
我创建了一个名为domain
的包,其中包含接口和Config
定义。
所以在domain/domain.go
中,我有以下代码:
package domain
type Config struct {
Cache
}
type Runner interface {
Run() string
}
type Cache interface {
// ...
}
根据上述提到的结构,运行者被组织在子包中。我不导出类型,而是在每个包中有一个函数来收集它们并将它们作为接口返回。
runner/blue/blue.go
:
package blue
import "my/domain"
func All(config domain.Config) (list []domain.Runner) {
list = append(list, fooRunner{Config: config})
list = append(list, barRunner{Config: config})
return
}
runner/runner.go
:
package runner
import (
"my/runner/blue"
"my/runner/red"
"my/runner/domain"
)
func All(config domain.Config) (list []domain.Runner) {
list = append(list, blue.All(config)...)
list = append(list, red.All(config)...)
return
}
英文:
I ended up creating a domain
package containing the interface and Config
definintions.
So in domain/domain.go
I have
package domain
type Config struct {
Cache
}
type Runner interface {
Run() string
}
type Cache interface {
// ...
}
The runners are structured in subpackages as mentioned above. I do not export the types but rather have a function in each package collecting all of them and returning it them as interfaces.
runner/blue/blue.go
:
package blue
import "my/domain"
func All(config domain.Config) (list []domain.Runner) {
list = append(list, fooRunner{Config: config})
list = append(list, barRunner{Config: config})
return
}
runner/runner.go
:
package runner
import (
"my/runner/blue"
"my/runner/red"
"my/runner/domain"
)
func All(config domain.Config) (list []domain.Runner) {
list = append(list, blue.All(config)...)
list = append(list, red.All(config)...)
return
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论