> Go interfaces generally belong in the package that consumes values of the interface type, not a package that implements the interface type. The implementing package should return concrete (usually pointer or struct) types. I like this rule. Most companies violate it everywhere. There are good times to ignore it but I always push for func NewThing To return something other than the interface type. The last Go interv…
That rule is not without its issues when pointers get involved, due to the typed nil problem.
Go Style
181–190 of 212 posts
Re: Go Style
#182Earlier quoted context omitted.
That rule is not without its issues when pointers get involved, due to the typed nil problem.
Yeah, this is a setup for hard to understand bugs unless you have a corresponding rule (imposed by a linter) that a concrete type cannot be cast into an interface and then checked against nil (mostly this means when returning a concrete type from a function it should be assigned to a freshly declared variable rather than re-using a variable that could already have an interface type.
Re: Go Style
#183> A little copying is better than a little dependency. Go takes this to an extreme, though. Generics helps, but the implementation is so limiting that it doesn't help much. > The general rule of thumb is that the length of a name should be proportional to the size of its scope and inversely proportional to the number of times that it is used within that scope. Some (most) of the go code I've seen where I work suffers…
Re: Go Style
#184Kinda amusing how the following section is complicated by the language's casing-based visibility feature https://google.github.io/styleguide/go/decisions#initialisms
Re: Go Style
#185>Concise Go code has a high signal-to-noise ratio. A few lines later: // Good: if err := doSomething(); err != nil { // ... } "Tell me, how many lights you see?"
Re: Go Style
#186> Go interfaces generally belong in the package that consumes values of the interface type, not a package that implements the interface type. The implementing package should return concrete (usually pointer or struct) types. I like this rule. Most companies violate it everywhere. There are good times to ignore it but I always push for func NewThing To return something other than the interface type. The last Go interv…
Interfaces are the most misused feature of Go. I think people like to prototype their API by typing in all the functions they intend to implement, so the interface acts as a template for their program that they can fill out. This, unfortunately, is not what they're for. I have a longer rant about this here: https://jrock.us/posts/go-interfaces/
An issue I can think of is for instance: consider a system where each time a new request comes in a new transaction is started. That situation would result in having a new `DBImpl struct` for each request. It seems that that last "but you probably only have one of these DB objects" doesn't hold. How would you tackle that issue?
Re: Go Style
#187Earlier quoted context omitted.
At first glance, that question makes sense; however, fmt doesn't cover all code format issues. Ex from the post: > Line length > There is no fixed line length for Go source code. If a line feels too long, it should be refactored instead of broken. If it is already as short as it is practical for it to be, the line should be allowed to remain long. > Do not split a line: > Before an indentation change (e.g., function…
I hate autoformatters/linters that frob with line length with a passion. I'm an 80-column kind of guy, but 81 columns can be just fine, and in some cases 90 or even 100 can be more readable than obsessively wrapping at 80 (or some other arbitrary value). There are a few (rare) cases where gofmt will wrap lines, but it mostly leaves it alone which is one of the better "features" IMHO. Many *fmt tools really got this w…
Re: Go Style
#188Earlier quoted context omitted.
Only the type Car matters, why would the function name tells you anything about mutation? It does not tells you if you receive *Car or Car or if it's a Car but pointers inside.
Because I want to know what function does?
func (d CarDB) func Car() (Car, error)
The above tells you everything you need to know. As for usage, again, the type and now also the variable names should let you infer everything you need.
func f(db *CarDB) { c, _ := db.Car() }
The function name makes as little of a guarantee as to the underlying "how" as these other factors.
Re: Go Style
#189Earlier quoted context omitted.
> Like having to declare a constant for the number of cents in a euro/dollar. I agree with your point, but this is a bad example. Naming these constant CentsInEuro and CentsInUSDollar is consistent with the style guide. As silly these examples are in isolation ( of course a cent is 1/100 of a euro or a dollar), if you are writing code that processes currencies beyond euro and dollars, you will quickly end up with (us…
Yeah maybe. I've worked on code where there were constants defined for minutes-in-hour, hours-in-day etc though, and that was just annoying; it's conceivable that our culture will one day decide that the Babylonians were idiots and we should use the French revolutionary clock instead, but I'll take my chances
For me, the use of those annoying constants is a form of mental relief: I don't have to remember why I'm dividing by 60 or 100 or whatever in this specific spot, it's written out in a way that reading it provides the context.
Re: Go Style
#190Earlier quoted context omitted.
Yeah, this is a setup for hard to understand bugs unless you have a corresponding rule (imposed by a linter) that a concrete type cannot be cast into an interface and then checked against nil (mostly this means when returning a concrete type from a function it should be assigned to a freshly declared variable rather than re-using a variable that could already have an interface type.
In practice this never happens unless you're violating other critical best practices like explicitly ignoring errors from constructors and trying to use the (nil) returned value anyway.