Go Interfaces: Is Not Net.Conn A Io.ReadWriteCloser?
I have a question about the uses of interfaces in go. I am still learning the language, so please forgive me if it is a stupid question.
I am playing with a little application that accept and handle TCP connections. Because I want to test the business logic and not the network magic, I am trying to keep it a little bit abstract using interfaces (so I can simulate net.Conn object using simple io.ReadWriteCloser
objects).
Here is my problem:
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
}
The error I see is:
net.Listener does not implement Accepter (wrong type for Accept method)
have Accept() (net.Conn, error)
want Accept() (io.ReadWriteCloser, error)
What I do not understand is why this is happening, because checking the documentation and the net lib source code, I see that net.Conn
is actually implementing io.ReadWriteCloser
.
What is my mistake? Thanks a lot!
Answer
I don't believe that stupid questions exist. If there is an honest question, there is an urge for knowledge, and it cannot be stupid by definition :)
Go relies on method signature to decide if two interfaces are the same. You cannot say that two method signatures are equal if they return essentially different types.
P.S.
If I express my opinion, I don't think your Accepter
abstraction is sound. I am struggling to explain what it does. Coming up with a good abstraction is hard, and I am pretty sure that the existing abstractions are already enough to do what you want -- test your business logic.
Let's say your business logic parses a JSON document and converts it to a human-readable text. You can pack it to a function with the following signature:
func DescribeDocument(src io.Reader, dst io.Writer) error {
...
}
You can pass an object that implements the net.Conn
interface to this function in a production code or the bytes.Buffer
object in a test code. No need to invent unnecessary abstractions :)
Related Questions
- → I can't do a foreign key, constraint error
- → laravel blade templating error
- → Image does not go in database with file name only tmp name saved?
- → ListView.DataSource looping data for React Native
- → If I yield to a Promise does it wait for the Promise to be resolved before continuing
- → Browser support for class syntax in Javascript
- → Authenticate with a cookie using laravel 5.1 and jwt
- → create log file on external server-Laravel
- → Sorting Children in Laravel : How do I sort children by name?
- → What is causing the web page to reload?
- → Where is the react-devtool?
- → Function Undefined in Axios promise
- → Onclick with argument causes javascript syntax error