我有两个独立的模块,让我们称之为
我想尽可能地将它们分开,它们不应该了解彼此的结构和界面。
FileSaver模块具有以下接口和结构:https://play.golang.org/p/OHObk0EPlG VideoFileProducer模块具有以下接口和结构: https://play.golang.org/p/iBOOaSPLc0
如你所见:
fileSaver.File
与videoFileProducer.VideoFile
fileSaver.FileSaver
界面与videoFileProducer.VideoFileSaver
界面相同(不同之处在于方法SaveFile
收到不同的__but_identical结构:File
和VideoFile
)fileSaver.fileSaverImpl
实现了fileSaver.FileSaver
接口videoFileSaver.NewVideoFileProducer
接收videoFileSaver.VideoFileSaver
interface 在主程序包中我想将FileSaver注入VideoFileProducer: https://play.golang.org/p/8B1iMCLLBE
我当然收到错误(https://play.golang.org/p/Eqr2ylKiQ6):
FileSaver没有实现VideoFileSaver(SaveFile方法的类型错误)
有SaveFile(文件)
想要SaveFile(VideoFile)
这两个结构完全相同,我们可以轻松地将VideoFile转换为File和File to VideoFile,但无论如何它们都有不同的类型。
简而言之,我想在Main包中创建FileSaver接口,将其转换为VideoFileSaver并将其发送到VideoFileProducer。
或以某种方式使FileSaver接口适合用作VideoFileSaver接口。
https://play.golang.org/p/NJRUCCp2xS
这个解决方案使用匿名结构,它可能太大而无法在很多地方将其声明为匿名(我只有一种方法,但在实际应用中可能有很多方法)。
https://play.golang.org/p/0rP4nn7j-T
我试图让结构(File,VideoFile)实现具有将其转换为指定匿名结构的方法的接口,但是没有成功。
https://play.golang.org/p/8Q1KHhzl_g
以前的方法,但使用接口{}。由于Interface Assertion(底层类型不同)而无法正常工作
有没有办法将界面直接转换为其他类型而不是底层类型(不使用反射)?
https://play.golang.org/p/xacNEjFG7D
我结合了最后两种方法并添加了使用开关来检查“底层接口是否与所需的相同”。所以现在我可以将VideoFileable用作Fileable。
然而,这不是最好看的解决方案,我仍然在寻找一种尽可能少使用匿名结构和接口{}的解决方案。
https://play.golang.org/p/4UPEmNkG-E
将VideoFileable转换为Fileable
https://play.golang.org/p/AneYQVm2Gc
VideoFile直接转换为文件
我对上述任何解决方案都不满意,仍然在寻找更干净的东西。
答案 0 :(得分:1)
删除VideoFile
结构并在两个地方使用File
结构。如果您不想要video
- > file
依赖关系,则必须将常见类型(File
和FileSaver
)提取到第三个包(这与你的匿名结构解决方案的原因相同 - 两个包都可以访问结构的"定义和#34;)
类型包
package types
type File struct {
Name string
Size int
}
type FileSaver interface {
SaveFile(File)
}
文件包
package file
import (
"fmt"
"types"
)
type fileSaverImpl struct{}
func (fs fileSaverImpl) SaveFile(f types.File) {
fmt.Println(f.Name, f.Size)
}
func NewFileSaver() types.FileSaver {
return fileSaverImpl{}
}
视频包
package video
import "types"
type VideoFileProducer struct{}
// NOTE: This function title is misleading; it doesn't actually
// create a `VideoFileProducer`, but instead it makes a new file
// and saves it with the provisioned `FileSaver`.
func NewVideoFileProducer(fileSaver types.FileSaver) {
fileSaver.SaveFile(types.File{Name: "Video", Size: 256})
}
主程序包
package main
import (
"file"
"video"
)
func main() {
NewVideoFileProducer(file.NewFileSaver())
}
答案 1 :(得分:0)
我已经实施了一个解决方案,正如我认为的那样,满足了要求。
它只是Adapter模式的一个实现。在高级模块层次结构中,我们创建了新的Service,它实现了VideoFileSaver接口并调用了FileSaver接口。
VideoFileSaver - (VideoFile) - >适配器 - (文件) - > FileSaver
https://play.golang.org/p/fO_ML6veWt
此解决方案的优点:模块的耦合极低,如果我们在适配器中添加额外的逻辑,File结构甚至可能与VideoFile完全不同
此解决方案的缺点:高度复杂性
我不建议您使用此解决方案。它只是满足了我的好奇心,但在实际项目中而不是它你应该(大多数)使用更简单的方法来做这些事情 - 比如在第三个模块中创建一个公共结构(在低级别的层次结构中)。正如weberc2所描述的那样。