Earlier quoted context omitted.
This makes me wonder: what if there was a language where variable names are determined according to the type, with the option of overriding with a custom name. So a variable of type http.Request would automatically be named “req”, the next one in scope would be “req2”, etc. If you think about it, when you solve a physics problem, for instance, you call every mass “m1”, “m2”, etc. Maybe this would be another step in G…
https://en.wikipedia.org/wiki/Hungarian_notation
Go Style
171–180 of 212 posts
Re: Go Style
#172Re: Go Style
#173> 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…
Slightly unrelated to Parent: I struggle very hard creating my own interfaces for my own programs. I haven't found any literature online teaching the _right way_ of coming up with your interface. For example, I very often struggle with function parameters and return types: should my interface functions only take basic type and return basic types? Can my interface function take more concrete types? Should my interface…
What you might want to do is also define an interface for what Git calls "commit-ish"[0] objects, and use that in place of *object.Commit. Then you could pass e.g. *object.Tag in place of *object.Commit.
Think of the interface as a contract between implementations and users of the data structure. Typically, you use an interface when multiple implementations are capable of fulfilling the same contract. If there's only one implementation, you likely don't need an interface—for instance, you can ignore my suggestion about abstracting commit-ish if you're pretty sure your checker would never be called for a tag.
Interfaces are often useful when testing, because a mock implementation can fulfill that same contract. For instance, you might implement a *object.MockCommit which just uses static values instead of actually operating on a Git repository, and then pass that for your commit-ish in unit tests for various Checkers.
[0] https://git-scm.com/docs/gitglossary#Documentation/gitglossa...
Re: Go Style
#174Earlier quoted context omitted.
I don't believe so. Imagine you're new to Go and you haven't mentally mapped all of these abbreviations. What would you rather read, `r` or `reader`?
Designing an API that "stutters" is a very common mistake that many programmers make. reader.Read() is pretty jarring. There is also nothing wrong with naming variables after what they're for instead of what they are. Consider io.Copy(dst, src). That's nicer than io.Copy(reader1, reader2).
It isn't a huge deal when the code is simple, e.g. you create a reader named `r` and in the next line you use it. That's easy to understand. The problem is that the pattern propagates. A few more lines of code are added, the reader is still named `r`. It's name `r` here, so we start putting it in a struct as `r`. Soon enough the codebase is littered with instances of `r`. Not great.
Re: Go Style
#175> Name constants based on their role, not their values. If a constant does not have a role apart from its value, then it is unnecessary to define it as a constant. This breaks the linter in most cases because "magic numbers". Like having to declare a constant for the number of cents in a euro/dollar. I think Google are right in this case, and linters need to be smarter.
> 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…
Re: Go Style
#176Earlier quoted context omitted.
Yeah i for for loops (in python) x for comprehensions, etc, make sense. But in general, single character variables make code really hard to read.
Yep, you should just use the best judgement, for example for distance, time in driving_metrics: speed = distance / time is a lot clearer than for d, t in driving_metrics: s = d / t even if it's used in a tiny scope once. But some things don't have a valuable meaning, or the meaning can trivially be inferred.
Re: Go Style
#177> 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/
I was struggling with this just today: Realizing I keep putting off writing tests for some modules because mocking a certain mega interface is a pain.
Your post gives me some great hints for things to try. Looking forward to experimenting with it.
Re: Go Style
#178Earlier quoted context omitted.
The constancy in Go makes this better. I have come to expect `r` to be an io.Reader or http.Request depending on context. There are a few interfaces in Go that are used heavily and I don't mind that people often use a single character for them. It's the same thing as everyone using `i` for iterators.
This makes me wonder: what if there was a language where variable names are determined according to the type, with the option of overriding with a custom name. So a variable of type http.Request would automatically be named “req”, the next one in scope would be “req2”, etc. If you think about it, when you solve a physics problem, for instance, you call every mass “m1”, “m2”, etc. Maybe this would be another step in G…
For sensitive infrastructure this makes sense, i surely wouldn't want to write other code like this.
Re: Go Style
#179Earlier quoted context omitted.
That wouldn't pass a code review where I work... Use a defer to do the unlock
I would also not allow it. I'm saying the problem is that core Go developers say "Go doesn't have exceptions", which is manifestly false, but causes people to not write exception safe code. But despite you and me, I'm saying there's a lot of broken code out there because of this doesn't-but-actually-does misinformation. And it's very annoying that you have to tell people to do: var i int func() { mu.Lock() defer mu.U…
Now this middle ground leaves you having to write triple verbose if err != null on every third line of your code and still not be safe from panics-that-shouldnt-have-been-panics.
As parent says, the only way panics can ever work is if the top-level never catches and recovers from them. I'm no expert in go but that would mean in such perfect world, defer should hardly ever be needed at all, not even for locks? Only for truly external resources? But now with popular web servers doing such recovery, the entire ecosystem got polluted and all need to handle it?
Re: Go Style
#180Earlier quoted context omitted.
The constancy in Go makes this better. I have come to expect `r` to be an io.Reader or http.Request depending on context. There are a few interfaces in Go that are used heavily and I don't mind that people often use a single character for them. It's the same thing as everyone using `i` for iterators.
This makes me wonder: what if there was a language where variable names are determined according to the type, with the option of overriding with a custom name. So a variable of type http.Request would automatically be named “req”, the next one in scope would be “req2”, etc. If you think about it, when you solve a physics problem, for instance, you call every mass “m1”, “m2”, etc. Maybe this would be another step in G…