
Useful Techniques in Go - luu
http://arslan.io/ten-useful-techniques-in-go
======
modulus1
'Use tagged literals for struct initializations'... I'd rather the compiler
help me make sure i've updated all uses appropriately when I add a new field.

~~~
farslan
Sometimes you don't use the field everywhere. Instead you add a new field to
extend a functionality, with a proper new method/function. So if you use tag
literals your existing code will still compile safely, and the tests will pass
too (assuming you didn't change the functions where the struct were used).

In a very large code base, not using tagged literals will just break anything.
Not sure you want it (for the case of extending). Removing will already break
it so no problems there.

(Disclaimer: I wrote the blog post)

~~~
modulus1
This is one of the trouble spots I have with Go.

Say I have 3 members that must be set, and 5 optional members. Go's solution
is to make the 3 critical members private so that someone using this struct
will probably figure out they should use a construction function. And doing
this means replacing all code that creates my struct with calls to a 'New'
function. With all this friction, people aren't likely to do the right thing.

At least in C++ with public members I can initialize appropriately in the
constructor. Of course littering my code-base with public members would be bad
practice in the first place.

~~~
NateDad
I used to worry about that, too, but in practice it rarely causes problems.
The constructor function will be grouped with the type it returns in Godoc,
and auto-complete generally will show both _type Foo_ and _func NewFoo_ when
you start typing "Foo". And generally you place the constructor function next
to the type it creates in the code as well.... it all contributes to it not
really being a problem.

------
Everlag
#8 is pretty great in that you can assign methods to custom types but not
builtins.

As an example, say I have []Card. If I want to sum all cards with a certain
color then I could

    
    
      Sum(cards []Card, color string)
    

but that is not great. Rather, I could use

    
    
      type Cards []Card
    

and then name a method

    
    
      (cards *Cards) Sum(color string) int
    
    

The benefit is that any []Card can now have Sum called on it without any
explicit casting.

I've been using this and find it to be clean.

------
ainar-g
Great article, especially #2. I found it strange how they didn't mention the
stringer tool[1] in #5 though.

[1]:
[https://godoc.org/golang.org/x/tools/cmd/stringer](https://godoc.org/golang.org/x/tools/cmd/stringer)

~~~
farslan
Author here. It was not written back then :) However it was used so much Rob
decided to write a tool to auto generate the String method. So it's now very
easy to generate and and it's also uses a much more efficient algorithm to
return the string :)

------
4ad
Regarding #6, starting with 1 is better than starting with 0, but even better
is using negative values:
[http://play.golang.org/p/ES8nNv4PeW](http://play.golang.org/p/ES8nNv4PeW)

Also regarding #6, the author didn't say it, but with iota is really trivial
to create power of two constants, so you can combine them:
[http://play.golang.org/p/rzD3Vl0C4q](http://play.golang.org/p/rzD3Vl0C4q)

For #5, he should have mentioned the stringer tool to maintain the list of
strings for you:
[https://godoc.org/golang.org/x/tools/cmd/stringer](https://godoc.org/golang.org/x/tools/cmd/stringer)

#10 really depends. There are many cases where you want to wrap your map, but
there are many other cases (more cases dare I say), where it doesn't really
matter because you only use the map (which is embedded in s struct) in very
few places (basically some methods of that struct).

The example also fails to synchronise reads.

A more important case that is not mentioned is that if you often initialise
once and read many times, without ever writing again, you don't need that kind
of wrapper in those scenarios.

And you also don't want that kind of wrapper even if you read and write often,
but read more than one value at a time. That hurts performance, but can even
limit your available semantics. With an explicit lock you can arrange so that
your map presents a consistent snapshot at all times.

~~~
sambeau
> but even better is using negative values

Honest question: Why?

~~~
4ad
Most small values in programs are positive (lengths, counts, etc), so it's
possible to write a value to something that should be initialised to a
constant by mistake, and you'll never know, since the ranges overlap.

But if you use negative values, and you write a positive value, when you see
it, you'll know.

Of course this is a very trivial thing, but it helped me many times.

Sometimes it's better to use typed constants with a custom type, then the Go
type system will help you and not let you assign things of a different type.
Note that I only said sometimes, in many cases it's better to use untyped
constants (or use primitive types rather than custom integers), and positive
integers because you can _calculate_ the constant corresponds to some value
from a delta, or from some other criteria, like here:

[https://github.com/golang/go/blob/54789eff385780c54254f822e0...](https://github.com/golang/go/blob/54789eff385780c54254f822e09505b6222918e2/src/cmd/internal/obj/arm64/asm7.go#L890)

with the definitions of constants here:

[https://github.com/golang/go/blob/54789eff385780c54254f822e0...](https://github.com/golang/go/blob/54789eff385780c54254f822e09505b6222918e2/src/cmd/internal/obj/arm64/7.out.go#L260)

Another thing useful when debugging is using constants with non-overlapping
peculiar ranges, rather than small integers, then simply by seeing a value in
a debugger (or in a print of a value without a String() method), you'll know
where that comes from.

~~~
sambeau
Thanks.

------
voidlogic
The shown label example for #2 is only one option, you could also use a simple
loop:

    
    
        for loop := true; loop; {
            select {
            case <-time.After(time.Second):
                fmt.Println("hello")
            default:
                loop = false
            }
        }
        fmt.Println("ending")

------
barosl

      type T struct {
          Foo string
          Bar int
          Qux string
      }
      
      t := T{"example", 123} // doesn't compile
      t := T{Foo: "example", Bar: 123} // OK
    

I find this behavior somewhat surprising. Contrary to the author's claim, I
would expect _both_ to fail to compile.

Reading the Go specification, it seems to be a valid behavior.

> An element list that contains keys does not need to have an element for each
> struct field. Omitted fields get the zero value for that field.[1]

I understand zeroing out the "unused" fields is common in low level
programming, but Go's behavior in this specific case feels a bit too implicit
for my taste.

[1] [https://golang.org/ref/spec](https://golang.org/ref/spec)

~~~
NeutronBoy
> Contrary to the author's claim, I would expect both to fail to compile.

I wouldn't - the first example is undefined (is 123 Bar or Qux? I guess
technically it should be Bar as without quotes it's an int... but it's not
unusual for int's to be cast into strings on assignment) and I would expect it
to fail. The second example explicitly states which variable is being
assigned.

edit: Thinking more about it, I guess it could go either way, but it's just
one of those things that once you do it once you know it.

~~~
barosl
I understand that in the latter case, what fields are being assigned is
clearer (albeit the former case can also adopt a similar order-based
strategy).

What I disagree is the "zeroing out" part. I don't want 0 or empty string to
be more "special" than ordinary values. Letting the compiler decide what
values are suitable if I omit them can be a cause of potential bug.

~~~
Vendan
Except that the spec states that the 0 value is "more special".

[https://golang.org/ref/spec#The_zero_value](https://golang.org/ref/spec#The_zero_value)

I personally like it this way, and it's better, imho, to have a "set
everything not specified to 0" step rather then "leave whatever garbage was
there"

~~~
barosl
Huh, I didn't know Go has a concept of implicit default value. In that aspect,
zeroing out in struct literals also makes sense.

However I would say that while default zero is better than garbage value,
failing to compile is even better than default zero. (e.g. the compiler
refuses to compile `var i int` in the first place) But I guess this is a
matter of preference.

~~~
reality_czech
If the code failed to compile unless you initialized all values, you could
never add a field to an existing type without updating all cases where you
were creating an instance. This would basically make refactoring impossible in
most real-world Go projects. You could potentially solve this problem by
forcing all object creation to be through special constructor functions (like
Java and Scala do), but that is not the Go way of doing things.

~~~
barosl
Yup, I'm much in favor of using a constructor, or even a trait, if such a
breakage can be problematic, because I believe types are part of an API (so
they should have been opaque types in the beginning). But I now understand
what an idiomatic Go way is.

------
vog
I disagree with #3.

If I change a data structure I want the compiler to tell me exactly which
parts of the code I should rethink. I do not want it to silently initialize
new fields with automatic values, as that may invalidate some of my
invariants.

Confusingly, it seems that the author is aware us this issue, as he
acknowledges exactly this issue #6, and provided a recommendation for easier
debugging of such situations.

~~~
NateDad
The idea is that, when you add a new field to the struct, the behavior should
not change if that field is given its zero value. Thus, all the rest of your
code continues to work as it did before.

If you change the code such that the zero value of that field makes the code
behave differently, then yes, it's your responsibility to go find all the
places that use the struct and update them. However, thanks to static typing
and nice namespaces, that's trivial.

------
ccannon
Re #7: Why have a function wrap it at all if all you're going to do is return
the function?

~~~
farslan
It's just an example. Of course the function has many other statements before
the returning function which is not shown, otherwise it doesn't make sense of
course.

------
jaytaylor
Lots of gems of good advice here!

Not sure I agree about #7 though, as I prefer the more explicit and log
friendly approach of not returning function call results directly.

------
akavel
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](https://github.com/fatih/vim-go) plugin. Especially with full oracle
support, it's a _killer_.

~~~
farslan
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 :)

------
ccannon
These are excellent tips.

