我正在从事一个 Go 项目,我正在使用一些相当大的第三方客户端库与一些第三方 REST api 进行通信。我的目的是将我的内部代码 API 与这些特定的依赖项分离。
在我的代码中将特定方法与这些库解耦很简单,因为我只需要功能的一个子集,并且我能够抽象出用例。因此,我在我的代码中引入了一种新类型来实现我的特定用例;然后,底层实现依赖于第三方依赖项。
我在理解如何找到良好的解耦方面遇到问题的地方是配置结构
。通常,我使用的客户端库提供了一些这种形式的功能
createResourceA(options *ResourceAOptions) (*ResourceA, error)
createResourceB(options *ResourceBOptions) (*ResourceB, error)
其中*ResourceA
和*ResourceB
是对应资源创建后的服务端配置。
不同的选项
是相当大的配置结构,用于具有大量字段、嵌套结构等的资源。总的来说,这些配置包含的选项比我的应用程序所需的更多,但最终总体重叠相当大。
因为我想避免我的内部代码必须导入特定的依赖项才能访问我想封装它们的配置结构。
我目前的封装方法是定义我自己的配置结构,然后我用它来配置第三方依赖项。举个简单的例子:
import a "github.com/client-a"
// MyClient implements my use case functions
type MyClient struct{}
// MyConfiguration wraps more or less the configuration options
// provided by the client-a dependency
type MyConfiguration struct{
Strategy StrategyType
StrategyAOptions *StrategyAOptions
StrategyBOptions *StrategyBOptions
}
type StrategyType int
const (
StrategyA StrategyType = iota
StrategyB
)
type StrategyAOptions struct{}
type StrategyBOptions struct{}
func (c *MyClient) UseCaseA(options *MyConfiguration) error {
cfg := &a.Config{}
if (options.Strategy = StrategyA) {
cfg.TypeStrategy = a.TypeStrategyXY
}
...
a.CreateResourceA(cfg)
}
正如使用此方法的示例所示,我可以封装第三方配置结构,但我认为此解决方案的扩展性不是很好。我已经遇到过一些示例,在这些示例中,我基本上是从代码中的依赖项中重新实现类型,只是为了抽象掉依赖项。
如果我的方法通常是错误的,我在这里寻找可能更复杂的解决方案和/或一些见解。
我的进一步研究:
我调查了struct embedding
是否对我有帮助。但是,由于配置包含重要成员,我最终也在我的调用代码中导入了依赖项以填充字段。
由于通常的准则似乎是接受接口(interface)返回结构
,我试图用这种方法找到一个好的解决方案。但是在这里我也可以得到一个相当大的接口(interface),并且在 go 标准库配置结构中似乎不通过接口(interface)使用。如果将配置隐藏在接口(interface)后面是 Go 中的一个好习惯,我找不到明确的声明。
总结一下:
我想知道如何从第三方库中抽象配置结构,而不会最终在我的代码中重新定义相同的数据类型。
最佳答案
一个非常简单的事情怎么样 - 在包装器包中重新定义您需要的结构类型?
我是新手,所以这可能不是继续进行的最佳方式。
package myConfig
import a "github.com/client-a"
type aConfig a.Config
那么你只需要导入你的myConfig包
import "myConfig"
// myConfig.aConfig is actually a.Config
myConfig.aConfig
不确定这是否有很大帮助,因为这不是真正的解耦,但至少你不需要在每个地方导入“github.com/client-a”
关于go - 封装第三方配置结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57203802/