英文:
Go interfaces: is not net.Conn a io.ReadWriteCloser?
问题
我对Go语言中接口的用途有一个问题。我还在学习这门语言,所以如果问题很愚蠢,请原谅。
我正在尝试编写一个小应用程序来接受和处理TCP连接。因为我想测试业务逻辑而不是网络操作,所以我试图使用接口来保持一定的抽象性(这样我就可以使用简单的io.ReadWriteCloser对象来模拟net.Conn对象)。
这是我的问题:
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
}
我看到的错误是:
net.Listener does not implement Accepter (wrong type for Accept method)
                have Accept() (net.Conn, error)
                want Accept() (io.ReadWriteCloser, error)
我不明白为什么会出现这个错误,因为根据文档和net库的源代码,我看到net.Conn实际上是实现了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!
答案1
得分: 1
错误告诉你问题所在:
net.Listener没有实现Accepter(Accept方法的类型错误)
                有 Accept() (net.Conn, error)
                需要 Accept() (io.ReadWriteCloser, error)
你的返回类型与接口定义的不同。仔细看一下错误信息中的have和want语句。
英文:
The error is telling you exactly what the issue is:
net.Listener does not implement Accepter (wrong type for Accept method)
                have Accept() (net.Conn, error)
                want Accept() (io.ReadWriteCloser, error)
You have a different return time than what your interface has defined. Take a second look at the error message have and want statement.
答案2
得分: 1
我不相信存在愚蠢的问题。如果有一个诚实的问题,那就有了对知识的渴望,根据定义,它就不会是愚蠢的 ![]()
Go语言依赖于方法签名来判断两个接口是否相同。如果两个方法签名返回的类型本质上不同,那么你不能说这两个方法签名是相等的。
附注:
如果我表达我的观点,我认为你的Accepter抽象不够合理。我很难解释它的作用。设计一个好的抽象很困难,我相信现有的抽象已经足够满足你的需求——测试你的业务逻辑。
假设你的业务逻辑是解析一个JSON文档并将其转换为可读的文本。你可以将它封装成以下签名的函数:
func DescribeDocument(src io.Reader, dst io.Writer) error {
    ...
}
你可以在生产代码中将实现了net.Conn接口的对象传递给这个函数,或者在测试代码中传递bytes.Buffer对象。没有必要发明不必要的抽象 ![]()
英文:
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 ![]()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论