Golang:我可以转换为 chan 接口

Posted

技术标签:

【中文标题】Golang:我可以转换为 chan 接口【英文标题】:Golang: Can I cast to chan interface 【发布时间】:2014-10-24 22:43:00 【问题描述】:

我正在尝试为订阅编写一个通用包装器,例如:

type Subscriber interface
    Subscribe(addr string) chan interface

假设我想使用一个库,其中有一个订阅方法,但它使用了chan library.Object。我希望能够做类似的事情:

func (s *mySubscriber) Subscribe(addr string) chan interface
    ch := make(chan library.Object)
    library.Subscribe(addr, ch)
    return chan interface(ch)

目前,我认为这样的演员阵容是不可能的。而且我不想修改底层库,因为包装器应该与库实现无关。

我见过Is there a way to cast Structs for sending over a channel,但在这种情况下,可以修改应用程序以满足需要。在这里,它不能。这可能吗?有没有更好的办法?

一种解决方案是将通用频道传递给订阅,并在chan library.Object 上无限期地等待并触发我的通用频道上的任何内容,但我并不特别喜欢必须引入另一个频道才能获得围绕类型转换。

【问题讨论】:

Go 没有“演员”的概念。进行类型转换、类型断言和接口(以及类型切换),仅此而已。类型转换最接近强制转换,例如C. 谈论强制转换和强制转换不起作用只会模糊您对必须通过使用类型转换来解决的问题的看法(在您的情况下不起作用!),巧妙地使用接口和适当的类型断言/开关可能与反射。 Go 中的大多数“通用”东西注定会失败或因深陷反思而变得缓慢。 【参考方案1】:

不,你不能只用演员表来做到这一点。正如您已经考虑过的,您必须使用额外的频道。幸运的是,已经有一个帮助库(免责声明:我写了它)。你想要Wrap 函数。

文档:https://godoc.org/github.com/eapache/channels#Wrap 代码:https://github.com/eapache/channels/

【讨论】:

数字。耻辱。也许将来作者会扩展类型切换以支持这一点。对于数组和映射,我们也有同样的问题,但至少在那里你可以循环遍历元素并将类型切换到 interface 。应该有某种方法可以使用频道,但也许有充分的理由不这样做? 原因不是这些类型具有根本不同的底层内存布局,因此它不像 C 中的“强制转换”那么简单。例如,一个 []structx,y int看起来与 []interface 完全不同,因此您不能只是“假装”它是一个,您必须进行手动转换。与简单的转换不同,转换可能很昂贵(正如您所说,您必须遍历每个元素),因此他们决定不隐藏它,因为它不是同一件事。【参考方案2】:

对于其他偶然发现此问题并想要一些内联代码的人:

// wrap a timeout channel in a generic interface channel
func makeDefaultTimeoutChan() <-chan interface 
  channel := make(chan interface)
  go func() 
    <-time.After(30 * time.Second)
    channel <- struct
  ()
  return channel


// usage
func main() 
  resultChannel := doOtherThingReturningAsync()
  cancel := makeDefaultTimeoutChan()
  select 
    case <-cancel:
      fmt.Println("cancelled!")
    case results := <-resultChannel:
      fmt.Printf("got result: %#v\n", results)
  

【讨论】:

以上是关于Golang:我可以转换为 chan 接口的主要内容,如果未能解决你的问题,请参考以下文章

GOLANG 变量

Golang: chan定义问题

将任意 Golang 接口转换为字节数组

Golang:将接口动态转换为类型化变量

PHP 协程:Go + Chan + Defer

PHP 协程:Go + Chan + Defer