我有两个独立的模块,我们称它们为
- 文件保护程序
- 视频文件制作者
我想尽可能地把它们分开,它们不应该知道彼此的结构和接口(interface)。
FileSaver 模块有这些接口(interface)和结构:https://play.golang.org/p/OHObk0EPlG VideoFileProducer 模块具有以下接口(interface)和结构: https://play.golang.org/p/iBOOaSPLc0
如你所见:
fileSaver.File
与videoFileProducer.VideoFile
相同
fileSaver.FileSaver
接口(interface)与videoFileProducer.VideoFileSaver
接口(interface)相同(区别在于方法SaveFile
接收不同但相同的结构:文件
和视频文件
)fileSaver.fileSaverImpl
实现了fileSaver.FileSaver
接口(interface)videoFileSaver.NewVideoFileProducer
接收videoFileSaver.VideoFileSaver
接口(interface)的实现
在 Main 包中,我想将 FileSaver 注入(inject)到 VideoFileProducer 中: https://play.golang.org/p/8B1iMCLLBE
当然我遇到了一个错误(https://play.golang.org/p/Eqr2ylKiQ6):
FileSaver does not implement VideoFileSaver (wrong type for SaveFile method)
have SaveFile(File)
want SaveFile(VideoFile)
这两个结构是相同的,我们可以很容易地将 VideoFile 转换为 File,将 File 转换为 VideoFile,但无论如何它们具有不同的类型。
简而言之,我想在 Main 包中创建 FileSaver 接口(interface),将其转换为 VideoFileSaver 并将其发送给 VideoFileProducer。
或者以某种方式调整 FileSaver 接口(interface)以用作 VideoFileSaver 接口(interface)。
工作解决方案#1(匿名结构)
https://play.golang.org/p/NJRUCCp2xS
此解决方案使用匿名结构,在很多地方将其声明为匿名可能会太大(我只有一种方法,但在实际应用中可能有很多)。
方法#1 无效(Fileable/VideoFileable 接口(interface))
https://play.golang.org/p/0rP4nn7j-T
我试图使结构 (File,VideoFile) 实现具有将其转换为指定匿名结构的方法的接口(interface),但没有成功。
无效方法 #1(接口(interface){})
https://play.golang.org/p/8Q1KHhzl_g
以前的方法,但使用接口(interface){}。由于接口(interface)断言而无法工作(底层类型不同)
有什么方法可以将接口(interface)直接转换为底层类型以外的其他类型(不使用反射)?
工作解决方案 #2(Fileable/VideoFileable + 接口(interface){})
https://play.golang.org/p/xacNEjFG7D
我结合了最后两种方法并添加了使用 switch 来检查“底层接口(interface)是否与所需接口(interface)相同”。所以现在我可以将 VideoFileable 用作 Fileable。
然而,这并不是最好看的解决方案,我仍在寻找尽可能少使用匿名结构和接口(interface)的解决方案。
工作解决方案 #3(Fileable/VideoFileable + 反射)
https://play.golang.org/p/4UPEmNkG-E
将 VideoFileable 转换为 Fileable
工作解决方案#4(接口(interface){} + 反射)
https://play.golang.org/p/AneYQVm2Gc
VideoFile直接转为File
我对上述任何解决方案都不满意,仍在寻找更干净的解决方案。
最佳答案
删除 VideoFile
结构并在两个地方使用 File
结构。如果您不想要 video
->file
依赖项,则必须提取常见类型(File
和 FileSaver
) 到第三个包中(这与您的匿名结构解决方案的工作原因相同——两个包都可以访问结构的“定义”)。
类型包
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())
}
关于go - 接口(interface)中的相同结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39807273/