Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

There's a difference though: in Java, the class declaration must mention the interface, but in Go it does not. In Go, you can declare an interface for a subset of a type's methods, in some other package, and use it there, without any change to the original type. You can create a new interface which a standard-library type satisfies!


Yes, and then be amazed that certain types match by accident interfaces with completely different semantics, just because the methods happen to be called the same by accident.

Then Start() will throw a rocket instead of starting the coffee machine. just because RocketLauncher and CoffeeMachine happen to have the same set of methods.


I have been programming in languages that theoretically permit this error for nearly twenty years. This error has happened to me a sum total of zero times. And a great deal of that time was in Python and Perl, where it's much easier than in Go where you have to exactly match the interface fully, not just on name.

I understand the concern. I'm not just saying that, the Haskell side of me still feels it. However, the pragmatic side of me says that it's not worth giving up the convenience, power, and decoupling of not having to explicitly declare conformance to interfaces to save myself zero bugs over nearly twenty years.

Now, HN is big and I'm abundantly sure there's a dozen people who can pop up with stories of when this bit them. But it's a question of tradeoffs; literally every day I program in Go I benefit from not having to declare interface conformance. Do you face this bug literally every day? Or even every month?

("What if you did have the problem and didn't notice?" Then apparently the cost wasn't that high, so cost/benefit still tilts in the direction of doing what Go or Python does. "What if it happens as the project gets bigger than what you've worked on?" Well, the dynamically-typed scripting products I've worked on tend to be past the size event horizon for other reasons, so we could never witness this being a huge problem because the code base can't get that large without also adopting practices that would tend to eliminate this anyhow. Statically typed I haven't gotten there, though I'm thinking statistically projects tokens would tend to diverge faster than they could converge here... i.e., even if I do somehow end up with twelve Start() functions that I don't intend to be a single interface, and all manage to have the exact same function signature, if they're separated by enough in the code that they just never cross, it still isn't a problem. With Go, you still have a hard time just accidentally passing them in... they have to traverse the codebase to get to the wrong place, across statically-typed paths.)


So not only does a type have to "accidentally" implement an interface, but also a programmer has to explicitly write code that has a value of that type in scope, and pass it to a function in a wildly different domain.

Sounds very much like only a theoretical gotcha.


It is a theoretical gotcha like writing unsafe code in C is.

Sure it is easy to avoid such gotchas in small code bases, handled by two or three programmers.

Scale it up to the typical sizes of enterprise projects, maintained by generation of programmers in distributed teams, with a goal of at least 10 years deployed in production and those gotchas happen all the time.


Reckon that class of bug has occurred often in large opensource Go projects?


Given that I am not an Oracle for large opensource Go projects, the answer is I don't know.

However it plays a role which programming languages I will advise our customers to use.

Currently I only advise the use of Go for those customers that need to work with Docker or K8s.


Compile-time duck typing :) To be fair, C++ templates have a similar problem. Rust nails this one with traits, I think.


C++17 has mechanism to validate if a type implements a certain "interface" (pure virtual base class) via type traits, if constexpr and enable_if, and hopefully with concepts a solution similar to traits will then be possible (already available on gcc).


You don't have to do this in Java anymore... Structural typing was added in Java 8 and is how method references are generally used. For example I use this often to avoid implementing Runnable when I already have a method satisfying the `void run()` contract on an existing implemented but with different name.

Edit: on reflection this may actually be duck typing not structural typing.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: