0

我正在尝试在第三方库之上创建一个层,在本例中为 libchan。这是我定义的接口:

type ReceiverStream interface {
    Receive(msg interface{}) error
}

type InboundTransport interface {
    WaitReceiveChannel() (ReceiverStream, error)
}

InboundTransport意味着作为 type 的替代品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
}

Transportlibchan 库在此处返回:

// libchan/session.go:62
func NewTransport(provider StreamProvider) libchan.Transport {
...
}

由于libchan.TransportInboundTransport分享了一种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接口是隐式的,这意味着只要返回类型实现与预期接口相同的方法,它就会通过编译。有什么我可以改变的,以便我可以将自定义接口叠加到第三方库返回的接口上吗?

TLDR:第三方库正在返回 interface 的对象TransportTransport接口指定了一个方法WaitReceiveChannel()。我有一个自定义接口InboundTransport,它还指定WaitReceiveChannel(). 我调用的第三方方法返回一个Transport通过 method实现的对象WaitReceiveChannel()。我假设它也会实现InboundTransport,因为后者也指定了WaitReceiveChannel()相同类型的 a。这是行不通的。为什么不?

4

1 回答 1

4

如您所知,Go 中的接口是隐式满足的。

但是,正如错误所述,

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)}
}
于 2018-06-24T09:23:34.793 回答