es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Interfaces de Go: ¿no es net.Conn un io.ReadWriteCloser?

Tengo una pregunta sobre los usos de las interfaces en Go. Todavía estoy aprendiendo el lenguaje, así que por favor discúlpame si es una pregunta estúpida.

Estoy jugando con una pequeña aplicación que acepta y maneja conexiones TCP. Debido a que quiero probar la lógica empresarial y no la magia de la red, estoy tratando de mantenerla un poco abstracta utilizando interfaces (así puedo simular un objeto net.Conn utilizando objetos simples de io.ReadWriteCloser).

Aquí está mi problema:

type Accepter interface {
    Accept() (io.ReadWriteCloser, error)
}

func NewTCPAccepter(address string) (Accepter, error) {
    accepter, err := net.Listen("tcp", address)
    if err != nil {
        return nil, err
    }
    return accepter, err
}

El error que veo es:

net.Listener no implementa Accepter (tipo incorrecto para el método Accept)
                tiene Accept() (net.Conn, error)
                quiere Accept() (io.ReadWriteCloser, error)

Lo que no entiendo es por qué está sucediendo esto, porque al revisar la documentación y el código fuente de la librería net, veo que net.Conn realmente implementa io.ReadWriteCloser.

¿Cuál es mi error? ¡Muchas gracias!

Tags:  , ,

Answer

  1. Avatar for davy.ai

    ¡En primer lugar, no existe tal cosa como una pregunta tonta! Hacer preguntas es una excelente manera de aprender y mejorar.

    En cuanto a tu problema, el inconveniente es que si bien net.Conn implementa io.ReaderWriterCloser, el tipo net.Listener devuelto por net.Listen no implementa tu interfaz Accepter, porque tiene una firma de método diferente para el método Accept. Específicamente, net.Listener.Accept devuelve un net.Conn y un error, mientras que tu método Accepter.Accept quiere devolver un io.ReaderWriterCloser y un error.

    Para solucionarlo, podrías crear un tipo envoltorio para net.Listener que implemente tu interfaz Accepter y usarlo en lugar del net.Listener sin formato. Aquí tienes un ejemplo de implementación:

    type tcpAccepter struct {
        listener net.Listener
    }
    
    func (a *tcpAccepter) Accept() (io.ReadWriteCloser, error) {
        conn, err := a.listener.Accept()
        if err != nil {
            return nil, err
        }
        return conn.(io.ReadWriteCloser), nil
    }
    
    func NewTCPAccepter(address string) (Accepter, error) {
        listener, err := net.Listen("tcp", address)
        if err != nil {
            return nil, err
        }
        return &tcpAccepter{listener}, nil
    }
    

    Esta implementación crea un nuevo tipo tcpAccepter que envuelve un net.Listener y proporciona una implementación del método Accept que devuelve un io.ReadWriteCloser. La función NewTCPAccepter ahora devuelve un Accepter que es una instancia de este tipo envoltorio.

    Al hacer esto, ahora puedes simular objetos net.Conn utilizando objetos io.ReadWriteCloser simples, como deseabas.

    ¡Espero que esto te ayude! Avísame si tienes alguna otra pregunta.

Comments are closed.