Hacker Timesnew | past | comments | ask | show | jobs | submitlogin

Yes, and no.

#3 - ("T{A:1, B:2} is better than T{1, 2}") - usually yes, and you'd want to write it multi-line for readability etc (see #4); but there are times, when you exactly want to benefit from the fact, that T{1, 2} is verified for completeness. And sometimes it can read better in table tests. (Sometimes. Only sometimes.)

#5 - as others said already, you can be smart and spare yourself some dumb work here and use golang.org/x/tools/cmd/stringer + go generate.

#6 - even better: start from 0, and make sure the 0 value is correct as the default value for unitialized variable/field! E.g.:

    const (
        Stopped State = iota
        Running
        Rebooting
        Terminated
    )
    // That said, this is assuming the "Stopped" can also mean "pre-running".
    // Otherwise, add a named "Uninitialized" state, or something.
#7 - I believe sometimes yes, sometimes not. Especially in longer functions, for the sake of "no surprises", it might be easier for readers to just keep multiple boring (read: regular) "return 0, err" blocks, and final "return x, nil". Also, it's then slightly easier to add more code to such a function (in growing codebase), and/or refactor it. Still, for cases when this results in a concise one-liner, totally yes!

#9 - as Author notes at the end, "This approach has the disadvantage that it pushes out the indentation and makes it harder to read. Again seek always the simplest solution." In my opinion, nice trick to know, but usually a "x := NewContext(...); defer x.Close()" or similar is the standard idiom.

NOTE: Especially for locks, I'd say you won't be adding anything to the block in future (see also: YAGNI). On the contrary, you might actually want to change it to a RWLock at some point, and then modify only some of the uses, and then the func would actually make it more annoying.

#10 - I'd say, only when you need it. If you don't need the lock, just use the map. If you need the lock... usually, I'd think you probably already have some higher level meaning for the "map", so I'd suggest to already wrap it in a proper type name & higher-level interface. "type FooRegistry { ... }; func (r * FooRegistry) Register(...)" etc. (And, actually, probably don't add the Delete() yet, until you really need it.) And probably you already have more complexity at this point that you'll want to nicely encapsulate in those funcs.

That said, all of the above is just my subjective opinion, too.

"#11" - By the way: if you're able to force yourself to use vim, absolutely have a look at the Author's https://github.com/fatih/vim-go plugin. Especially with full oracle support, it's a killer.



5) I've replied on another comment, but stringer was not written back then. Totally agree on that one :)

6) Makes sense, but starting it with +1 makes it really easy to see if it's initialized or not (if you care about or need the knowledge of external explicit initialization).

11) Thanks akavel :)




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: