'How to write idiomatic constructor
I'm confused about the constructors in Go. Most constructors I've seen return a struct, but 'Effective Go' suggests that an interface can be returned in some cases, according to the rule of 'Generality'.
I trust 'Effective Go' to provide good ideas, but this doesn't seem to follow the principle of 'accept interfaces, return structs'. I guess that many types implement an interface and nothing more than that, so in that case it would be common to see constructors which return interfaces.
Another related statement is that interfaces should be defined by the consumer, but 'Generality' means that the interface is defined by the producer.
Can someone clarify?
Solution 1:[1]
It depends a bit on your preference and how you view things. Coming from OOP background my take is: there is no point in the constructor if you cannot enforce it. Adding the constructor means - you must supply these values when instantiating this item. If your struct is public, it will be misused and instantiated bypassing the constructor. So it makes sense that the constructor returns the public interface and the struct is private (lowercase). If the struct is public, there is no point in the constructor, because you cannot enforce it. Writing code is a dialogue between writer and reader, making a struct public and having a constructor would tell the reader - here you have the constructor, but you also have a public struct and that would mean that constructor usage is arbitrary. If that is the case, go with that setup
Solution 2:[2]
In most cases constructor functions return concrete types (or pointer to a type). The situations in which returning interfaces might be a good idea is when calling factory functions or builder functions in which underlying concrete type satisfies that interface.
Consider error interface for example, when you call http.NewRequest underlying concentrate error type can be of net.Error, net.DNSError etc. Now try to think how are you going to create an api like this without an error interface if function returns concrete type? Only solution to it I can think of is to create a massive error type for net package and add fields for extra information, but its most probably much harder to maintain, test that kind of error type and not to mention memory bloat.
Whether you choose to return concrete type or an interface is a design choice, some guidelines exists to give solution to common scenarios.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Edwin Dalorzo |
