在Go中传递一些事物作为接口的通道

在Go中传递一些事物作为接口的通道

本文介绍了在Go中传递一些事物作为接口的通道的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的程序有一个流水线结构,并且我刚刚实现了一个缓存过滤器,如果已经处理过的数据版本位于缓存中,则直接发送内容到输出。



<$ p code $ func run(在chan downloader.ReadyDownload)chan CCFile {
out:= make(chan CCFile)
processQueue:= make(chan downloader.ReadyDownload)
go cache.BypassFilter(in,processQueue,out)
//将缓存的已处理版本写出,如果存在的话
//否则将输入重定向到processQueue
go process(processQueue ,出)
退出
}

问题是我的程序有像这样的多个地方,以及许多种类的结构(如此片段中的ReadyDownload和CCFile)正在通过这些渠道传递。它们都实现了这个接口。
$ b $ $ $ $ $ $ $ $ $ $ $ $' b $ b Key()string
}

所以我的BypassFilter这里:
$ b $ pre $ func(c Cache)BypassFilter(in chan ProcessItem,process chan ProcessItem,bypass chan ProcessItem)

但是这会导致以下错误:

在函数参数


$ b $中键入chan utils.ProcessItem时,不能用于(type chan downloader.ReadyDownload) b

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

  foo:= downloader.ReadyDownload {} 
var bar utils.ProcessItem
bar = foo

因此,我对Go类型和界面的理解非常有限我问这个问题:它们是什么东西和其他东西的渠道,这使得类型不兼容?我应该怎么做才能使它工作?假设我有一个ReadyDownloads频道。是将数据转发到函数所需的唯一方法,让我们将接口{}的通道作为参数,创建一个新的接口通道{},将其传递给函数,并从ReadyDownloads的通道读取内容并将它们提供给其他渠道?

解决方案

这两个是不同的类型:

  processQueue chan ReadyDownload 

process chan ProcessItem

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



您需要做的是制作<$ c $类型的所有频道c> chan ProcessItem

  func运行(在chan ProcessItem中)chan CCFile {
o ut:= make(chan CCFile)
processQueue:= make(chan ProcessItem)
go cache.BypassFilter(in,processQueue,out)
//将缓存的已处理版本写出如果它存在
//否则将输入重定向到processQueue
go process(processQueue,out)
返回
}

要详细了解这是为什么(对于切片,但同样适用于频道),您可以阅读以下维基页面:

b
$ b


My program has a pipeline structure, and I just implemented a caching filter that sends stuff directly to output if the already processed version of data is in the cache.

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
}

The problem is that my program has multiple places like this, and many kind of structs (like ReadyDownload and CCFile in this snippet) are being passed through the channels. They all implement this interface

type ProcessItem interface {
    Source() string
    Target() string
    Key() string
}

so my BypassFilter() function signature looks like this:

func (c Cache) BypassFilter(in chan ProcessItem, process chan ProcessItem, bypass chan ProcessItem)

But this brings about the following error:

cannot use in (type chan downloader.ReadyDownload) as type chan utils.ProcessItem in function argument

Although ReadyDownload certainly implements ProcessItem. For example, this works without problems:

foo := downloader.ReadyDownload{}
var bar utils.ProcessItem
bar = foo

So, my (yet) very limited understanding of Go types and interfaces brings me to ask this question: Is it the fact that they are channels of something and something else, that makes the types incompatible? What should I do to make it work? Let's say that I've got a channel of ReadyDownloads. Is the only way to forward the data to a function that takes, let's say channel of interface{}s as a parameter, to create a new channel of interface{}s, pass that to the function and read stuff from the channel of ReadyDownloads and feed them to the other channel?

解决方案

These two are different types:

processQueue chan ReadyDownload

process chan ProcessItem

You can put a ReadyDownloader value in a channel of type chan ProcessItem (if it implements the interface), but you cannot convert one channel type to another, in the same way that you cannot convert a []T slice into a []interface{} slice, another common confusion similar to this one.

What you need to do is make all the channels of type 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
}

To read more about why this is (for slices, but the same applies for channels), you can read the following go-wiki page:

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

这篇关于在Go中传递一些事物作为接口的通道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-16 23:47