Golang:通过空接口传递通道

huangapple go评论79阅读模式
英文:

Golang: Passing channels through empty interfaces

问题

我正在尝试做一些看起来应该很简单的事情,直到我阅读了一些资料,现在它看起来应该非常复杂。;-)
我创建了一个测试模式来说明:
http://play.golang.org/p/Re88vJZvPT

最基本的是,我想要一个函数,可以从一个通道读取数据并将其输出到另一个通道。很简单。只要使用所示的pusher函数,测试就可以实现这一点。
然而,这种方法的问题是,如果我想要推送不同类型的数据,我需要为每种类型的数据编写不同的pusher函数。
过去,我曾经用空接口做过类似的事情,因为pusher代码不关心数据结构中的内容。但是,当我处理不关心数据结构的通道时,我无法弄清楚该怎么做。

为了说明我想要实现的概念,请参见pusher_naive_generic函数。

然而,那也不起作用,所以我又阅读了更多的资料,得出的结论是利用反射来实现,最后你可以看到我的pusher_reflect_generic函数(显然,这个函数无法实现与其他函数相同的预期功能,它只是展示了我在卡住之前的进展)。
但是,这仍然失败,因为我无法从包含通道的接口中获取从该通道读取的结构。

希望代码比我的话更能说明我想要实现的目标。我可以通过明确为每种类型编写代码来使所有这些工作正常,但我无法弄清楚如何为任何未来的类型编写代码。

英文:

I'm trying to do something that seems like it should be trivial until I read up and now it seems like it should be really complex. Golang:通过空接口传递通道
I've knocked up a test pattern to illustrate:
http://play.golang.org/p/Re88vJZvPT

At the most basic I'm trying to have a function that can read data from a channel and spit it out on another one. Easy. The test does this as long as you use the pusher function shown.
However the problem with this is that doing it this way I would need a different pusher function for each type of data I want to push through it.
Now I've done similar things in the past with an empty interface as nothing in the pusher code cares about what's in the data structure. What I can't figure out is when I'm dealing with channels of an un-cared-about data structure.

To illustrate the concept of what I'm trying to achieve please see the function pusher_naive_generic.

However that doesn't work either so more reading up implied the way to do it was making use of reflection and finally you see my pusher_reflect_generic function(obviously this won't achieve the same intended function as the others it's showing where I got to before getting stuck).
Which still fails because I can't get from an interface that contains a chan to the structure read from that chan.

Hopefully the code makes more sense of what I'm trying to achieve than my words actually do. I can make all of this work by explicitly coding for every type, but what I can't figure out how to do is code it for any future type.

答案1

得分: 2

如果我正确理解了你的问题,那么这可能是解决方案:

func forwardChannel(i interface{}, o interface{}) {

    it, ot := reflect.TypeOf(i), reflect.TypeOf(o)

    if it != ot {
        panic("forwardChannel: both arguments must be of the same type")
    }

    iv, ov := reflect.ValueOf(i), reflect.ValueOf(o)

    for {
        v, k := iv.Recv()
        if !k {
            break
        }
        ov.Send(v)
    }

    ov.Close()

}

请注意,如果io不是通道类型,RecvSendClose会引发错误。

英文:

If I have understood your question correctly, then this might be the solution:

http://play.golang.org/p/xiDO7xkoW4

func forwardChannel(i interface{}, o interface{}) {

	it, ot := reflect.TypeOf(i), reflect.TypeOf(o)

	if it != ot {
		panic("forwardChannel: both arguments must be of the same type")
	}

	iv, ov := reflect.ValueOf(i), reflect.ValueOf(o)

	for {
		v, k := iv.Recv()
		if !k {
			break
		}
		ov.Send(v)
	}

	ov.Close()

}

Note that Recv, Send and Close panic if i and o are not channels.

huangapple
  • 本文由 发表于 2016年2月26日 21:23:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/35652902.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定