在 Go 中将事物通道作为接口通道传递

Gol*_*nks 5 generics interface channel go

我的程序有一个管道结构,我刚刚实现了一个缓存过滤器,如果已经处理过的数据版本在缓存中,它会直接将内容发送到输出。

func Run(in chan downloader.ReadyDownload) chan CCFile {
    out := make(chan CCFile)
    processQueue := make(chan downloader.ReadyDownload)
    go cache.BypassFilter(in, processQueue, out)
        // writes the cached, already processed version to out if it exists
        // otherwise redirects the input to processQueue
    go process(processQueue, out)
    return out
}
Run Code Online (Sandbox Code Playgroud)

问题是我的程序有多个这样的地方,并且通过通道传递了许多类型的结构(如此代码段中的 ReadyDownload 和 CCFile)。他们都实现了这个接口

type ProcessItem interface {
    Source() string
    Target() string
    Key() string
}
Run Code Online (Sandbox Code Playgroud)

所以我的 BypassFilter() 函数签名如下所示:

func (c Cache) BypassFilter(in chan ProcessItem, process chan ProcessItem, bypass chan ProcessItem)
Run Code Online (Sandbox Code Playgroud)

但这会带来以下错误:

cannot use in (type chan downloader.ReadyDownload) as type chan utils.ProcessItem in function argument
Run Code Online (Sandbox Code Playgroud)

尽管 ReadyDownload 确实实现了 ProcessItem。例如,这可以毫无问题地工作:

foo := downloader.ReadyDownload{}
var bar utils.ProcessItem
bar = foo
Run Code Online (Sandbox Code Playgroud)

所以,我对 Go 类型和接口的(但)非常有限的理解让我问这个问题:它们是某物其他物的通道,这是否导致类型不兼容?我该怎么做才能让它发挥作用?假设我有一个 ReadyDownloads 频道。是将数据转发到函数的唯一方法,该函数将接口的通道作为参数,以创建新的接口通道,将其传递给函数并从 ReadyDownloads 的通道读取内容并将它们馈送到另一个通道?

ANi*_*sus 6

这两个是不同的类型:

processQueue chan ReadyDownload

process chan ProcessItem
Run Code Online (Sandbox Code Playgroud)

您可以将ReadyDownloader值放入类型的通道中chan ProcessItem(如果它实现了接口),但是您无法将一种通道类型转换为另一种通道类型,就像您无法将切片转换[]T[]interface{}切片一样,这是与此类似的另一种常见混淆。

您需要做的是将所有通道设置为以下类型chan ProcessItem

func Run(in chan ProcessItem) chan CCFile {
    out := make(chan CCFile)
    processQueue := make(chan ProcessItem)
    go cache.BypassFilter(in, processQueue, out)
        // writes the cached, already processed version to out if it exists
        // otherwise redirects the input to processQueue
    go process(processQueue, out)
    return out
}
Run Code Online (Sandbox Code Playgroud)

要了解更多有关原因的信息(对于切片,但同样适用于通道),您可以阅读以下 go-wiki 页面:

http://code.google.com/p/go-wiki/wiki/InterfaceSlice