Don’t communicate by sharing memory, share memory by communicating.
Pass things to concurrent functions via channels
Concurrency is not parallelism.
Refactor your code to their functional units and go func to run them
Channels orchestrate; mutexes serialize.
Learning when to use the correct concurrency primitive is a skill.
The bigger the interface, the weaker the abstraction.
I always find people who say “Reader” is the best interface pompos. It is akin to artsy fartsy people saying a blank canvas is the best painting.
Make the zero value useful.
A very pretty way of avoid construction
var b bytes.Buffer
foo := bufio.NewWriter(&b) // Will need to call foo.Flush() before reading b though
Useful default means that we can avoid constructors. This is quite useful, and can be a gate between production env and dev env. For production, we can pass in a useful flag that will initialize some component. For local dev, we can check if the flag is set. If it is not, then nil
is used. Define method on nil such that they are noop methods.
interface{} says nothing.
Avoid using this where possible.
Gofmt’s style is no one’s favorite, yet gofmt is everyone’s favorite.
Yes, but we have a whole slew of other tools like go vet
, go metalinter
, go imports
. Yes, it is nice that there is one good base formatter.
A little copying is better than a little dependency.
The point is the avoid unnecessary compilation and increased file size. The talk mentioned writing tests that uses other packages to keep things in sync. That’s a cute idea.
Syscall must always be guarded with build tags.
Because Syscalls are by definition architecture dependent.
Cgo must always be guarded with build tags.
God knows what happens when you run a c program.
Cgo is not Go.
You throw away all the good guarantees, such as static type checking, garbage collection out of the window.
With the unsafe package there are no guarantees.
Use this with the expectation code will break in the future.
Clear is better than clever.
KISS. I often wonder if refactoring and reusing functions by going to higher orders is a good call.
Reflection is never clear.
Leave it for code gen instead
Errors are values.
Don’t think of them as control flow operations.
I wonder if this means it is sensible to return meaningful partial results, similar to Write() (int, error)
.
Don’t just check errors, handle them gracefully.
Don’t just lazily return nil, err
.
Design the architecture, name the components, document the details.
A good name can do the heavy lifting of explaining what it does
Documentation is for users.
Write for user of the method, struct. Don’t just describe what the method does, instead, write about why/when it should be used.
Don’t panic.
Maybe arguable for init? E.g. regex.MustParse()