go - 接口(interface)中的相同结构

标签 go dependency-injection interface type-conversion

我有两个独立的模块,我们称它们为

  1. 文件保护程序
  2. 视频文件制作者

我想尽可能地把它们分开,它们不应该知道彼此的结构和接口(interface)。

FileSaver 模块有这些接口(interface)和结构:https://play.golang.org/p/OHObk0EPlG VideoFileProducer 模块具有以下接口(interface)和结构: https://play.golang.org/p/iBOOaSPLc0

如你所见:

  • fileSaver.FilevideoFileProducer.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 依赖项,则必须提取常见类型(FileFileSaver ) 到第三个包中(这与您的匿名结构解决方案的工作原因相同——两个包都可以访问结构的“定义”)。

类型包

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/

相关文章:

go - Go中根据依赖执行任务

java - 如何从方法中的内部接口(interface)返回值?

iPhone 开发 - 手动旋转 View

c++ - 连接接口(interface)中声明的 QT 信号

java - 将属性注入(inject)到同一类的不同实例(Spring 框架)

curl - Beego 如何访问使用 multipart/form-data header 提交的参数?

GO111MODULE=on(错误加载模块要求)

git - 如何避免仅在 Docker 内部发生的 `go get` `unknown revision` 问题?

spring - 如何在 Drools 规则中使用 Spring 服务?

asp.net-mvc - 如何在 ASP.NET MVC 的 RegisterGlobalFilters 方法中进行依赖项注入(inject)