Live data from Hacker News

Go Style

google.github.io

181–190 of 212 posts

Re: Go Style

#181

> 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.

Typed nil isn't a problem, it indicates a crucial lack of understanding about interfaces, which should be resolved with education, not restricting good API design.

Re: Go Style

#182

Earlier 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.

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.

Re: Go Style

#183
post #45

> 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…

"A little copying is better than a little dependency" is not talking about anything that would be solved by generics or metaprogramming, which suggests that you are completely misunderstanding. It's saying to not import a large library if you only need one five line helper function from it. Generics do not help, and the advice could be applied to any programming language.

Re: Go Style

#184
post #18

Kinda amusing how the following section is complicated by the language's casing-based visibility feature https://google.github.io/styleguide/go/decisions#initialisms

In practice it's not an issue and is quite sensible/intuitive how it works, at least for English speakers.

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?"

What's wrong with this? The code is doing... exactly what it says. Call doSomething and if it returns an error do something else. What part of that is noise?

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/

Wow, I find this quite interesting, however, there are probably some real downsides to this? Maybe someone else can highlight some of those.

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

#187

Earlier 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…

I hate this about default rustfmt.

Re: Go Style

#188
post #82

Earlier 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?

Assuming Car() is a receiver function, you should be able to infer "how" the Car is "fetched" based on the type receiving the function call.

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

#189
post #21

Earlier 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

More realistically, software will run on other celestial bodies which have different time periods (e.g. the moon, mars, asteroids, etc.).

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

#190

Earlier 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.

I think it doesn’t happen for errors because the error interface is almost always what is returned. It doesn’t seem that hard across if this style guide were followed: https://news.ycombinator.com/item?id=33566422
Post reply on HN