英文:
How to call different function code based on parameters(Pluggable) in Golang
问题
我想实现一个项目,根据不同的启动参数或配置文件,实现几个不同的功能,即一个可插拔的功能集合。期望的效果是,main.go 可以根据参数调用 cmd/<feature>/<feature>.go
中的 run function。
项目比较复杂,需要进行扩展。
是否有可以学习的 设计模式
或 现有项目
,如果有的话,希望能给予建议。
非常感谢您的帮助。
英文:
I would like to implement a project that enables several different features based on different startup parameters or configuration files
, a pluggable feature set. The desired effect is that main.go can call the run function in cmd/<feature>/<feature>.go
according to the parameters
├── cmd
│   ├── feature1
│   │   └── feature1.go
│   └── feature2
│   └── feature2.go
├── pkg
│   ├── feature1
│   │   └── feature1.go
│   └── feature2
│   └── feature2.go
└── main.go
Projects are complex
and need to be extended
Is there a design pattern
or an existing project
that can be learned, if there is hope you can give advice
I really appreciate any help with this.
答案1
得分: 1
这里有两个需要讨论的事情。
- 项目结构
- 可扩展性和可维护性
如果你想构建一个单一的应用程序,我建议你在cmd
目录下有一个模块,所有的功能都在pkg
目录下(每个应用程序一个cmd目录/文件):
├── cmd
│ └── main.go
└── pkg
├── features
│ ├── feature1.go
│ ├── feature2.go
│ └── feature3.go
└── service
└── service.go
如果功能集应该是可扩展的,你可能需要一个接口,所有的功能都将实现该接口,例如:
type Feature interface {
Run(context.Context) error
}
此外,你将拥有一个应该使用提供的功能构建的服务:
// pkg/service/service.go
type Service interface {
Run(context.Context) error
}
// service是Service的实现
type service struct {
features []Feature
}
// Run运行服务。服务运行功能。
func (s *service) Run(ctx context.Context) error {
for _, f := range s.features {
err := f.Run(ctx)
// 检查错误
}
// 你的其余代码
}
创建一个具有任意功能集的服务应该很容易。最简单的方法是将功能切片传递给服务构造函数:
func NewService(features []Feature) Service {
return &service{features: features}
}
将功能传递给服务构造函数的更优雅的方法是使用函数选项模式。
英文:
There're two things that should be discussed here.
- Project structure
- Extendability and maintainability
If you want to build a single application, I would recommend you to have one module in the cmd
directory and all features in the pkg
directory (one cmd dir/file per application):
├── cmd
│ └── main.go
└── pkg
├── features
│ ├── feature1.go
│ ├── feature2.go
│ └── feature3.go
└── service
└── service.go
If the feature set should be extendable, you probably will need an interface, that will be implemented by all features, for example:
type Feature interface {
Run(context.Context) error
}
Also, you will have a service that should be constructed with provided features:
// pkg/service/service.go
type Service interface {
Run(context.Context) error
}
// service is the Service implementation
type service struct {
features []Feature
}
// Run runs the service. The service runs the features.
func (s *service) Run (ctx context.Context) error {
for _, f := range s.features {
err := f.Run(ctx)
// check the error
}
// the rest of your code
}
It should be easy to create a service with an arbitrary set of features. The simplest way is to pass a slice of features to the service constructor function:
func NewService(features []Feature) Service {
return &service{features: features}
}
A more elegant way to pass your features to the service constructor is to use functional options pattern.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论