-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: Go 2: implement an interface based on function signature if method name is ambiguous #37280
Comments
I have bumped into this when using 3rd party marshaling libraries such as msgp which defines generic names for its interface methods. |
For a suggestion like this, please identify real code that this would help. This issue has been recognized as a theoretical problem in Go since the beginning. It has never been changed because the problem is rarely seen in actual code. It's very unlikely that we would change the language in this way without specific examples where it would make a difference. See also this FAQ entry: https://golang.org/doc/faq#overloading. The rule of matching methods by name is very simple and easy to understand. Matching methods by signature is much more subtle. |
I mainly made this issue because I read said criticism, where someone apparently did run into this problem. I personally have not encountered this yet, but I thought that maybe for some Google projects you had already encountered this problem. I wanted to see if other people had really encountered the problem, or if it is, as you say, largely academic. So far, one person has replied that that they did run into this problem when using msgp. I will wait for more feedback on this issue, and if no one shows up with more examples of this issue, I will close it. You may label it "hold" or so if that makes more sense. For the record I would like to state that after more thought, I found a workaround involving some pointers to the top level object: package main
import "fmt"
type Fooer interface {
Foo() int
}
type Fooer2 interface {
Foo() string
}
type DoFoo1 struct {
*DoFoo
}
type DoFoo2 struct {
*DoFoo
}
func (d DoFoo1) Foo() int {
return d.FooerFoo()
}
func (d DoFoo2) Foo() string {
return d.Fooer2Foo()
}
func (DoFoo) FooerFoo() int {
return 400
}
func (DoFoo) Fooer2Foo() string {
return "Foo"
}
type DoFoo struct {
DoFoo1
DoFoo2
}
var _ Fooer = DoFoo1{}
var _ Fooer2 = DoFoo2{}
func main() {
df := DoFoo{}
df.DoFoo1 = DoFoo1{&df}
df.DoFoo2 = DoFoo2{&df}
var f1 Fooer = df.DoFoo1
var f2 Fooer2 = df.DoFoo2
fmt.Printf("%d %s\n", f.Foo(), f2.Foo())
} https://play.golang.org/p/GCzx_OR9zEm Like this we can simulate "overloading" the different functions as is appropriate. |
As mentioned above, the current language rule is very simple and easy to understand: methods are matched by name, and nothing else. Without examples of real code that would be significantly helped, we aren't going to make this change. Therefore, this is a likely decline. Leaving open for four weeks for final comments. |
Seeing the lack of interest in this issue, and that a plausable workaround is available, I will withdraw this proposal immediately to leave the Go team more time to work on more pressing issues. Thanks for your consideration. |
Background
I found the following criticism of Go language here: https://www.quora.com/What-reasons-are-there-to-not-use-Go-programming-language?share=1
Several points are mentioned, but the one that caught my eye is the following:
I thought this could perhaps be fixed by putting two structs that implement the two interfaces together in one struct, however doesn't quite work out nicely. See the following example:
https://play.golang.org/p/Q6Vwpb019-6
The compiler complains:
Proposal
In this case, there is no actual ambiguity, in because the signature of the two Foo functions is different. The Foo from DoDoo1 implements Fooer, and the Foo from DoFoo2 implements Fooer2. The code above should work. The compiler should automatically select the correct function based on the type signature of the methods to resolve the ambiguous name. Only if none of the candidates has required type signature, or if there are several with the required signature, then the compiler should raise an error. This would then also address the main criticism of interfaces I cited above.
This is not just a theoretical issue, there are indeed cases where it's hard to implement two different interfaces, normally from different packages, with one type, because there are name clashes.
Proposal template
I am experienced, I have been using Go for 10 years since before v1.0.
Batch files, Basic, C, C++, D, Java, Javascript, Lua, Objective-C, Oberon, Pascal, PHP, Python, R, Ruby, Shell scripts, Visual Basic, ...
It would not make Go easier to learn, but also not harder. It is something a novice might reasonably consider that it should work.
AFAIK, no.
This proposal would help people who like the person criticising go would like to satisfy two different interfaces which have methods that have the same names but different signatures. .
Yes, currently this is a compilation error. This proposal is to loosen an existing restriction.
Before:
The code above can be made to work by selecting a member of the DoFoo struct to satisfy one of the interfaces.
After:
The compiler automatically select the sub-struct that correctly implements the interface.
This would also work for functions with interface parameters.
The new compiler feature has to be implemented, documented and tested.
The gopls tool may or may not have to be updated to know about this new feature.
Low, the compiler has at do a few extra field look ups, but it should already have that data available.
None.
At compile time the compiler selects the sub-struct that satisfies the interface automatically. I think this should be relatively easy to implement.
"Interface types" needs to be amended to specify this new feature of the language.
It extends the current interface feature in a small but useful way.
No.
Not directly, apart from the fact that error is an interface.
No.
The text was updated successfully, but these errors were encountered: