doz95923 2014-03-25 01:13
浏览 27
已采纳

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

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?

  • 写回答

2条回答 默认 最新

  • dousi2553 2014-03-25 01:42
    关注

    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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度