标准库通过多种方式解决了此问题:
1)没有“中央”注册表
这样的示例是不同的哈希算法。该
crypto包仅定义
Hash接口(类型及其方法)。具体实现在不同的封装(其实子文件夹,但并不需要如此),例如
crypto/md5和
crypto/sha256。
当您需要“哈希器”时,您可以明确说明您要的实例并实例化该实例,例如
h1 := md5.New()h2 := sha256.New()
这是最简单的解决方案,并且还可以为您提供良好的分离:
hash程序包不必了解或担心实现。
如果您知道或可以先决定要使用哪种实现,则这是首选的解决方案。
2)具有“中央”注册表
这基本上是您建议的解决方案。实现必须以某种方式注册自己(通常在包
init()函数中)。
image包装就是一个例子。该软件包定义了
Image接口及其一些实现。在
image/gif,
image/jpeg和等不同的程序包中定义了不同的图像格式
image/png。
所述
image封装具有
Depre()其解码并返回一个函数
Image从指定
io.Reader。通常不知道哪种类型的图像来自阅读器,因此您不能使用特定图像格式的解码器算法。
在这种情况下,如果我们希望图像解码机制是可扩展的,那么注册是不可避免的。最干净的方法是在包
init()函数中,该函数通过在导入时为包名指定空白标识符来触发。
请注意,此解决方案还使您可以使用特定的实现对图像进行解码
Depre(),例如,具体的实现也提供了功能
png.Depre()。
那么最好的方法呢?
取决于您的要求。如果您知道或可以决定所需的实现,请选择#1。如果您不确定还是不知道并且需要可扩展性,请选择#2。
…或者继续下面列出的#3。
3)提出第三个解决方案:“自定义”注册表
您仍然可以方便地将“中央”注册表与界面和实现分开,而以“自动扩展性”为代价。
这个想法是你在package中有接口
pi。你必须在包的实现
pa,
pb等等。
然后,您将创建一个
pf具有所需“工厂”方法的程序包,例如
pf.NewClient()。该
pf包可以指包
pa,
pb,
pi而不创建循环依赖关系。



