英文:
Golang: Can I cast to chan interface{}
问题
我正在尝试编写一个通用的订阅包装器,类似于:
type Subscriber interface {
Subscribe(addr string) chan interface{}
}
假设我想要使用一个库,该库中有一个subscribe
方法,但它使用了chan library.Object
。我想要做的是:
func (s *mySubscriber) Subscribe(addr string) chan interface{} {
ch := make(chan library.Object)
library.Subscribe(addr, ch)
return chan interface{}(ch)
}
目前,我不认为这样的类型转换是可能的。而且我不想修改底层库,因为包装器应该对库的实现是不可知的。
我看到过类似的问题:https://stackoverflow.com/questions/13425490/is-there-a-way-to-cast-structs-for-sending-over-a-channel,但在那种情况下,可以修改应用程序以满足需求。在这里,无法修改。这种转换是否可能?是否有更好的方法?
一种解决方案是将一个通用的通道传递给Subscribe
,并在chan library.Object
上无限期等待,并将接收到的任何内容发送到我的通用通道,但我不太喜欢为了绕过类型转换而引入另一个通道。
英文:
I am trying to write a general purpose wrapper for subscriptions, something like:
type Subscriber interface{
Subscribe(addr string) chan interface{}
}
Suppose there is a library I want to use which has a subscribe method in it, but which uses a chan library.Object
. I would like to be able to do something like:
func (s *mySubscriber) Subscribe(addr string) chan interface{}{
ch := make(chan library.Object)
library.Subscribe(addr, ch)
return chan interface{}(ch)
}
Currently, I don't believe such a cast is possible. And I don't want to modify the underlying library, since the wrapper should be agnostic to library implementations.
I've seen https://stackoverflow.com/questions/13425490/is-there-a-way-to-cast-structs-for-sending-over-a-channel, but in that case the application can be modified to suit the need. Here, it can't. Is this possible? Is there a better way?
One solution is to pass in a general purpose channel into Subscribe, and to wait indefinetely on chan library.Object
and fire anything that comes through on my general channel, but I didn't particularly like having to introduce another channel just to get around the type cast.
答案1
得分: 7
不,你不能只用一个转换来实现这个。你必须使用一个额外的通道,就像你已经考虑到的那样。幸运的是,已经有一个辅助库可以做到这一点(免责声明:我写过它)。你需要使用Wrap
函数。
- 文档:https://godoc.org/github.com/eapache/channels#Wrap
- 代码:https://github.com/eapache/channels/
英文:
No, you can't do this with just a cast. You have to use an extra channel, as you have already considered. Fortunately, there is a helper library for this already (disclaimer: I wrote it). You want the Wrap
function.
- Documentation: https://godoc.org/github.com/eapache/channels#Wrap
- Code: https://github.com/eapache/channels/
答案2
得分: 2
对于其他遇到此问题并希望使用内联代码的人:
// 将超时通道包装在通用接口通道中
func makeDefaultTimeoutChan() <-chan interface{} {
channel := make(chan interface{})
go func() {
<-time.After(30 * time.Second)
channel <- struct{}{}
}()
return channel
}
// 使用示例
func main() {
resultChannel := doOtherThingReturningAsync()
cancel := makeDefaultTimeoutChan()
select {
case <-cancel:
fmt.Println("已取消!")
case results := <-resultChannel:
fmt.Printf("得到结果:%#v\n", results)
}
}
希望这对你有帮助!
英文:
For anyone else that stumbles on this issue and wants some inline code:
// 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)
}
}
答案3
得分: 0
我可以使用Go泛型来完成这个任务:
func Wrap[T any](from chan T) chan interface{} {
to := make(chan interface{})
go func() {
var val T
for {
val = <-from
to <- val
}
}()
return to
}
func Unwrap[T any](from chan interface{}) chan T {
to := make(chan T)
go func() {
var val interface{}
for {
val = <-from
to <- val.(T)
}
}()
return to
}
这段代码使用了Go的泛型功能,通过Wrap
函数将一个类型为T
的通道转换为一个类型为interface{}
的通道,而Unwrap
函数则将一个类型为interface{}
的通道转换为一个类型为T
的通道。
英文:
I was able to do this with Go generics:
func Wrap[T any](from chan T) chan any {
to := make(chan any)
go func() {
var val T
for {
val = <-from
to <- val
}
}()
return to
}
func Unwrap[T any](from chan any) chan T {
to := make(chan T)
go func() {
var val any
for {
val = <-from
to <- val.(T)
}
}()
return to
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论