3 ms·
>The difference between Go and Java is that in Go a type need not declare its adherence to an interface up front. Go can't declare adherence up front, and in m
by owlstuffing 2y ago
>The difference between Go and Java is that in Go a type need not declare its adherence to an interface up front.
Go can't declare adherence up front, and in my view that’s a problem. Most of the time, explicitly stating your intent is best, for both humans reading the code and tools analyzing it. That said, structural typing has its moments, like when you need type-safe bridging without extra boilerplate.
- duskwuff 2y agoYou can assert that your type implements an interface at compile time, though, e.g. var _ AssertedInterface = &MyType{}
- relistan 2y agoOne of the main uses for interfaces in Go is defining the contact for _your_ dependencies. Rather than saying your function takes a socket, if you only ever call Write(), you can take a Writer, or define another interface that is only the set of functions you need. This is far more powerful than declaring that your type implements an interface up front. It allows for things like e.g. multiple image libraries to implement your interface without knowing it, enabling your project to use them interchangeably. And as another commenter said, you can have the compiler verify your compliance with an interface with a simple (though admittedly odd looking) declaration.
- williamdclt 2y ago> It allows for things like e.g. multiple image libraries to implement your interface without knowing it That virtually never happens. Seriously, what would be the odds? It’s so much more usual to purposefully implement an interface (eg a small wrapper the writer thingy that has the expected interface) than to use something that happens to fit the expected interface by pure chance. It’s not a structural vs nominal problem but other, typescript is structural but has the implements keyword so that the interface compliance is checked at declaration, not at the point of use. You don’t have to use it and it will work just like Go, but I found that in 99% of cases it’s what I want: the whole point of me writing this class is because I need an interface implementation, might as well enforce it at this point.
- deleted 2y ago[deleted]
- relistan 2y agoIt happens all the time because e.g. third party developers follow the same patterns in the standard lib. And it was designed that way. Another example: logging libs are frequently quite similar. Even though the stdlib didn’t define that interface, you can still make your own that works for lots of libs. But even if you don’t use that part of it, it’s still great to limit the scope of your dependency. Less to mock, more flexible code. You obviously don’t like this and I’m not going to convince you, I think. But this is really one of the best features of Go.
- relistan 2y agoExample: https://pkg.go.dev/image https://pkg.go.dev/image This library (and some 3rd parties) have a lot of implementations of image types. But without any inheritence or interface declaration on their part I can make something that will do image size calculations by defining an interface that only contains Bounds() Rectangle Now, any of those types can be passed into my function to do checking. Another example. The stdlib log package didn't define an interface (they should have) and the stdlib logger looks like this: https://pkg.go.dev/log https://pkg.go.dev/log However, lots of people have made drop in replacements that implement the same method signature. By defining an interface you can swap in the stdlib logger or a 3rd party without the stdlib implementing that interface. So yeah, the stdlib implemented the interface I defined in my code "by accident" and that's a great thing.