Live data from Hacker News

Go Style

google.github.io

151–160 of 212 posts

Re: Go Style

#151

Go is absurd. It's opinionated in all the wrong ways. > Functions that return something are given noun-like names. > // Good: > func (c Config) JobName(key string) (value string, ok bool) > A corollary of this is that function and method names should avoid the prefix Get. > // Bad: > func (c Config) GetJobName(key string) (value string, ok bool) That's dumb. I'd like a function to be GetJobName to indicate that it do…

> That's dumb. I'd like a function to be GetJobName to indicate that it doesn't mutate anything. Maybe CreateJobName to indicate mutation. Just JobName is useless.

It can't mutate anything with a non-pointer receiver. Mostly.

> how do you reliably "test" its emptiness

See time.IsZero() for an example.

Re: Go Style

#152
post #63

Earlier quoted context omitted.

I just use reader//req. Code is instantly easier to read for me personally and no time has been wasted. It's all preference, of course.

This is much nicer for other people coming into this. It's the same problem with spoken language and slang, slang is better if you know it, worse if you don't.

Sorry to be pedantic (well, not really it's M.O. for a hacker news commentor after all, isn't it?) , but as someone who knows a few languages, slang is not an issue with spoken languages at all. You learn a language by full immersion with other speakers, who impart that knowledge unto you. Unless all you are doing is conversing with grammaticians and newscasters, you will pick up on regional and local differences, euphemisms, and slang.

Re: Go Style

#153

In my opinion the hardest style rules to accept when trying to use this guide are: 1. Do not create "assertion libraries" like `assertEqual(x, y)` [1] 2. Leave testing to the Test function [2] 3. Intialisms (HTTPURL, IOS, gRPC) [3] 4. Function formatting [4] For the record I'm not saying I disagree with these. I just think that folks coming from other languages have a lot of built in muscle memory to do it other ways…

I've read the assertions section a few times and I still don't understand the argument. How is: if got == nil { t.Errorf("blog post was nil, want not-nil") } Better than assert.NotNil(t, got, "blog post") ? They seem to suggest that you lose context, but their "Good" examples are similarly devoid of context.

Coming from Swift development I first missed having a collection of assertion functions for testing, but I've come around to the go testing patterns. I do think test assertion libraries usually result in less useful messages, and you end up having to implement a new function for every type of comparison under the sun.

(One thing I absolutely abhor is those assertion DSLs similar to rspec)

Re: Go Style

#154
post #69

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…

I agree that most types come with a natural variable name. However, in many cases a more descriptive name is way appropriate. On top of my mind: - Multiple variables of the same type. How are you supposed to distinguish between req and req2? Compare it to something like "apiReq" and "cdnReq" - Primitive types, that does not inherently carry a domain value. An integer called "seconds" or "max_offset" has a lot more me…

The real question from this example is: why are you creating two http requests in the same scope before using them?

I've been writing Go cloud stuff for the better part of a decade and "req" for a request has never been ambiguous because I go ahead and send the request and process the response before sending another one, at which point I can just reassign the variable and let the first one fall out of scope.

Re: Go Style

#155
post #63

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

I just use reader//req. Code is instantly easier to read for me personally and no time has been wasted. It's all preference, of course.

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

Re: Go Style

#156

Earlier quoted context omitted.

There's also a bit of Fitt's Law in here as well - I find it a lot harder to select, or put my cursor in, a single letter variable. So if I want to rename `i` to something else, I must carefully select `i`, whereas with a longer variable I find it easier to put my cursor in the middle of `index` and hit F2.

If you are using a mouse for things like this you already lost though.

Most developers use their mouse quite often.

Re: Go Style

#157

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

I think that it is fair to say Go considers error handling to be signal, not noise.

This position has obviously prompted a philosophical war and not everyone agrees, but the two statements are consistent under Go's philosophy.

Re: Go Style

#158

> 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 function take interface types?

I'd love to be directed to a guide on how to create a good interface.

As an example, here's a recent interface declaration I wrote:

    type Checker interface {
        Check(context.Context, *object.Commit, bool) (bool, []string, error)
        Name() string
        Describe() string
    }
My program runs through a list of commits and runs "Checks" on them. These checks "pass (true)" or "fail (false)".

I want the user of my package to be in charge of the implementation details of a "Check", so I created the interface above.

Is it OK for the Check() function to take a *object.Commit? Should I instead pass a `SHA string` and let the implementer figure out how to get a *object.Commit from that string?

Re: Go Style

#159
post #63

Earlier quoted context omitted.

I just use reader//req. Code is instantly easier to read for me personally and no time has been wasted. It's all preference, of course.

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

Re: Go Style

#160

Earlier quoted context omitted.

Why not writing a small wrapper around time.Parse? func ParsedTimeOrNil(s string) *time.Time { t1, err := time.Parse(time.RFC3339, s) if err != nil { return nil } return &t1 }

Hiding errors like that is going to make it hard to figure out what is going on as more and more wrappers like this pile up. If time.Parse is failing, you either have bad input or a bug, right? If you are ok with this failing without even logging the error, something might be wrong with the design.

Hiding errors saves less than a second of typing, at the cost of making every five minute bugfix a one day bugfix. Don't do it.

You can't build your own programming language inside of Go. If you absolutely cannot mentally handle functions returning an error and you having to type "if err != nil { fix the problem }", you really need to find a different programming language. But, errors happen all the time, and handling them correctly is the difference between an unreliable piece of garbage that randomly fails and software you and your users can trust. There is, unfortunately, no automation around making software reliable.

Post reply on HN