Structuring go interfaces with subpackages

huangapple go评论101阅读模式
英文:

Structuring go interfaces with subpackages

问题

我正在开发我的第一个真正的Go应用程序,并试图理清代码文件的结构。

我的代码的主要部分将是一些实现了共同接口的类型。

type Runner interface {
  Run() string
}

它们将位于一个包中。由于接口实现的数量将非常大,我希望将它们(语义上)分成几个子包。

runner/
  blue/
  red/

Runner 的实现需要访问一些在应用程序的其他地方定义的接口(例如 CacheSecret)。这些接口目前在单独的包中定义和实现。我的计划是使用一个包含所有这些实用接口的 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>



huangapple
  • 本文由 发表于 2022年4月23日 18:06:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/71978689.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定