我正在尝试在第三方库之上创建一个层,在本例中为 libchan .这是我定义的接口(interface):
type ReceiverStream interface {
Receive(msg interface{}) error
}
type InboundTransport interface {
WaitReceiveChannel() (ReceiverStream, error)
}
InboundTransport
是 Transport
类型的替代:
// libchan.go
type Transport interface {
// NewSendChannel creates and returns a new send channel. The receive
// end will get picked up on the remote end of the transport through
// the remote calling WaitReceiveChannel.
NewSendChannel() (Sender, error)
// WaitReceiveChannel waits for a new channel be created by the
// remote end of the transport calling NewSendChannel.
WaitReceiveChannel() (Receiver, error)
}
只是为了上下文,这是 libchan.Receiver
定义(请注意它匹配我的 ReceiverStream
:
// libchan.go
type Receiver interface {
// Receive receives a message sent across the channel from
// a sender on the other side of the underlying transport.
// Receive is expected to receive the same object that was
// sent by the Sender, any differences between the
// receive and send type should be handled carefully. It is
// up to the application to determine type compatibility, if
// the receive object is incompatible, Receiver will
// throw an error.
Receive(message interface{}) error
}
Transport
由 libchan 库返回 here :
// libchan/session.go:62
func NewTransport(provider StreamProvider) libchan.Transport {
...
}
由于 libchan.Transport
和 InboundTransport
共享一个 WaitReceiveChannel() (ReceiverStream, error)
方法,我想我应该能够子一个为另一个,像这样:
func (ln SpdyListener) Accept(addr string) InboundTransport {
var listener net.Listener
var err error
listener, err = net.Listen("tcp", addr)
if err != nil {
log.Fatal(err)
}
c, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
p, err := spdy.NewSpdyStreamProvider(c, true)
if err != nil {
log.Fatal(err)
}
return spdy.NewTransport(p)
}
但是我得到一个错误:
cannot use spdy.NewTransport(p) (type libchan.Transport) as type InboundTransport in return argument:
libchan.Transport does not implement InboundTransport (wrong type for WaitReceiveChannel method)
have WaitReceiveChannel() (libchan.Receiver, error)
want WaitReceiveChannel() (ReceiverStream, error)
我假设这个错误的意思是 ReceiverStream
的类型与 libchan.Receiver
不匹配,但我认为 golang 接口(interface)是隐式的,这意味着只要由于返回类型实现了与预期接口(interface)相同的方法,因此它将通过编译。有什么我可以更改的,以便我可以将自定义接口(interface)叠加到第三方库返回的接口(interface)上吗?
TLDR:第三方库正在返回接口(interface) Transport
的对象。 Transport
接口(interface)指定了一个方法 WaitReceiveChannel()
。我有一个自定义接口(interface) InboundTransport
,它还指定了 WaitReceiveChannel()
。我正在调用的第三方方法返回一个对象,该对象通过方法 WaitReceiveChannel()
实现了 Transport
。我假设它也会实现 InboundTransport
,因为后者还指定了相同类型的 WaitReceiveChannel()
。这是行不通的。为什么不呢?
最佳答案
如您所知,Go 中的接口(interface)是隐式满足的。
但是,正如错误所述,
WaitReceiveChannel() (libchan.Receiver, error)
和
WaitReceiveChannel() (ReceiverStream, error)
是两种不同的方法类型,导致libchan.Transport
未隐式实现InboundTransport
。
要解决此问题,您必须围绕 libchan.Transport
编写一个薄包装器,以正确实现 InboundTransport
。
type TransportWrapper struct {
t *libchan.Transport
}
func (w *TransportWrapper) WaitReceiveChannel() (Receiver, error) {
return w.t.WaitReceiveChannel()
}
// ...
func (ln SpdyListener) Accept(addr string) InboundTransport {
var listener net.Listener
var err error
listener, err = net.Listen("tcp", addr)
if err != nil {
log.Fatal(err)
}
c, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
p, err := spdy.NewSpdyStreamProvider(c, true)
if err != nil {
log.Fatal(err)
}
return &TransportWrapper{spdy.NewTransport(p)}
}
关于go - 尝试使用 go 接口(interface)实现多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51008324/