4 ms·
> Do not need to explicitly declare interfaces a struct conforms to. Which comes with its own (sometimes dangerous) downsides. > 2. Do not need to declare typ
by apta 7y ago
> Do not need to explicitly declare interfaces a struct conforms to.
Which comes with its own (sometimes dangerous) downsides.
> 2. Do not need to declare types of variables inferred on initialization.
Java has `var` for quite some time now:
var foo = new Foo<Bar>();
is valid.
> Syntax for slice, map and struct literals
I assume you mean overloading `[]` for slices and maps. This is a nice feature (C# and Kotlin already do this). But it doesn't reduce boilerplate by much in practice.
- throwaway894345 7y ago> Which comes with its own (sometimes dangerous) downsides. I don't buy this. I've heard the theoretical arguments to the contrary, but I've never (in 7 years of consistent Go use) heard of anyone being bit by this in practice--certainly not to any significant consequence. On the other hand, implicit interfaces materially benefit nearly every project in the Go ecosystem. I would make this tradeoff all day every day.
- apta 7y agoThere was an actual bug in the golang standard library precisely due to this feature, so it's far from theoretical. Secondly, I found that in practice, it doesn't buy you much, and on the contrary, makes working with code more difficult (even with an IDE). It's valuable information to know what interface(s) a type implements, not to mention finding all types down the hierarchy that implement a given interface (much more tedious and resource hungry with golang).
- throwaway894345 7y agoOne incident doesn't make it "far from theoretical". I concede that it's "vanishingly small", however. > Secondly, I found that in practice, it doesn't buy you much, and on the contrary, makes working with code more difficult (even with an IDE). I don't know about you, but I don't like having to write boilerplate to make a third party class implement a first party interface. > It's valuable information to know what interface(s) a type implements, not to mention finding all types down the hierarchy that implement a given interface (much more tedious and resource hungry with golang). How is that information valuable? The only thing I can think of is "I want to change the interface and consequently I need to update the implementations". In which case, just change the interface and the compiler will tell you what broke. As for "resource hungry", who cares? I'll trade 50ms of computing time per search (note that this is a generous figure) if it means developers don't need to maintain "implements" annotations and the corresponding boilerplate discussed above.
- apta 7y ago> How is that information valuable? It's useful when you want to know where a certain concrete type is being passed as an interface. If you have a type Foo that has functions bar() and baz(), then it becomes very tedious to see where Foo is being used as a `Barrer` (in golang style), `Bazzer` or even `BarrerBazzer` because it now automatically implement all three interfaces. Another use case is that it becomes awkward to define "tag" interfaces (look at Rust's `Send` trait for instance). Now you're forced to define an interface with a function `isSend` or something and hope that no one else declares another interface with the same signature and passes in types that implement that. Again, more bug-prone behavior. > I'll trade 50ms of computing time per search (note that this is a generous figure) On any non-trivially sized project, it takes way longer than that to look up implementations of interfaces in the IDEs I've used so far. You're looking at 30s+ sometimes.
- throwaway894345 7y ago> It's useful when you want to know where a certain concrete type is being passed as an interface. If you have a type Foo that has functions bar() and baz(), then it becomes very tedious to see where Foo is being used as a `Barrer` (in golang style), `Bazzer` or even `BarrerBazzer` because it now automatically implement all three interfaces. That's just a generalization of the example I gave, and the same solution applies (although there are probably automated solutions). Unless there are other special cases that you have to do so frequently that the solution previously mentioned is too tedious, then I don't see what the fuss is about. > Another use case is that it becomes awkward to define "tag" interfaces (look at Rust's `Send` trait for instance). Now you're forced to define an interface with a function `isSend` or something and hope that no one else declares another interface with the same signature and passes in types that implement that. Again, more bug-prone behavior. I don't know how to take this comment seriously. The odds of someone implementing isSend and passing it to the wrong interface have to be astronomically low. The frequency of such bugs must be approaching zero. It's patently unreasonable to consider this to be "bug prone", moreover, if you're really, really concerned about it, randomly generate your private method name to whatever degree of entropy you prefer. > On any non-trivially sized project, it takes way longer than that to look up implementations of interfaces in the IDEs I've used so far. You're looking at 30s+ sometimes. File those bugs with the IDEs. Any IDE worth its salt holds the set of types in memory. Even if the set is just a list/array (as opposed to some data structure that is indexed by the interfaces they implement), it should take no time at all to filter that to the set that implements the interface, even if there are tens of thousands of types.
- ptx 7y ago> Java has `var` for quite some time now Well, it was only added in the latest LTS release, which was released a little over a year ago. (Or a few months before that if you used the non-LTS Java 10.) It's about time – C# had it since 2007.