3 ms·
Yep - return concrete types, but also make sure you have an assertion along the lines of: var _ IfaceType = &ConcreteType{} Somewhere, else you risk not k
by robmccoll 4y ago
Yep - return concrete types, but also make sure you have an assertion along the lines of:
var _ IfaceType = &ConcreteType{}
Somewhere, else you risk not knowing that a change to ConcreteType broke is implementation of IfaceType in a way that you might not know about until a rare runtime code path is executed.
- masklinn 4y ago> Somewhere, else you risk not knowing that a change to ConcreteType broke is implementation of IfaceType in a way that you might not know about until a rare runtime code path is executed. Why would runtime be involved? Surely if ConcreteType doesn't satisfy the interface anymore then the compiler will catch that at any site where a ConcreteType is being used as / cast to an IfaceType? Or are you talking about iface->iface side-cast?
- jrockway 4y agoThe compiler will catch it at the point of use, but it's clearer if the error is at the point of declaration. Consider: type FooReader struct{} var _ io.Reader = FooReader{} func (r FooReader) Raed(p []byte) (int, error) { return 0, nil } Before you even use FooReader as an io.Reader, you can find that you typo'd "Read". This is useful in practice because you probably wrote FooReader to have a bunch of other methods that aren't implementing io.Reader, and it's possible that your tests for this object don't actually ever use it as an io.Reader. So you won't notice this mistake until someone tries it elsewhere in the codebase. It also acts as documentation that you intend for this thing to be an io.Reader. But I also recommend that you document Read as "// Read implements io.Reader." to be extra explicit.
- masklinn 4y agoHah, how’s that for an endorsement of structurally typed interfaces.