DEV Community

Jay R. Wren
Jay R. Wren

Posted on • Updated on

How to write Go

#go

I find myself on a team where where small tiny little mistakes are being made when writing Go. I'd like to collect a reference of how to write better Go. I am putting it here.

  1. https://go.dev/doc/effective_go
  2. https://go.dev/doc/faq
  3. https://github.com/golang/go/wiki/CodeReviewComments
  4. https://go-proverbs.github.io
  5. https://github.com/golang-standards/project-layout/issues/10 (pkg directory should not be recommended for us)
  6. https://github.com/golang-standards/project-layout/issues/117
  7. If the last 2 don't convince you, then: https://github.com/go-standard/project-layout
  8. Consider: https://github.com/uber-go/guide/blob/master/style.md
  9. More: https://rakyll.org/style-packages/

Things I see newer Go programers do which should be avoided:

Too many packages

Circular packages are not allowed in Go, unlike Java, C#, Javascript, Ruby, or Python. This means that you can structure yourself into a corner which requires great feats of moving things around.
When should you create a new package? Only when you must!
You'll know when you must.
Common musts:

  • Another executable and you want it smaller so you avoid including some larger packages.
  • You are building libraries (packages) consumed by 3rd-parties and you want those 3rd parties to have a choice regarding sizing their resulting executables. Let YAGNI and KISS guide you.

Remember, Go is a derivative of C more than any other language, not Python, Ruby, JavaScript, C#, or Java. The compilation artifact of those languages are different than C or Go. If you aren't very familiar with C, then your instinct in Go is probably misguiding.

Defining an unused interface

https://github.com/golang/go/wiki/CodeReviewComments#interfaces says it best.

Go's implicit interfaces allow consumers to create the interface they need far better than you can.

Common or util packages

NEVER.
https://dave.cheney.net/2019/01/08/avoid-package-names-like-base-util-or-common

Don't store context

https://go.dev/blog/context

You'll notice the RFC for "relax recommendation against storing context" https://github.com/golang/go/issues/22602 is still open. Never expect this to be closed.

In fact, if you read that open issue, you'll learn that it is not requesting to relax the recommendation, but to clarify it and the clarification is, "don't store context"

No unused parameters (unless you are implementing an interface)

This really applies to ALL programming languages, but us Go programmers like it because we have so many "no unused..." rules already.

Clear is better than clever

https://go-proverbs.github.io https://www.youtube.com/watch?v=PAAkCSZUG1c&t=14m35s

Beware of reading too much

This is basic defensive programming which is often ignored which Go stdlib helps make trivial.

You've made your net/http Request and have a response:

Do:

body, err := io.ReadAll(io.LimitReader(resp.Body, 32768))
Enter fullscreen mode Exit fullscreen mode

Don't:

body, err := io.ReadAll(resp.Body)
Enter fullscreen mode Exit fullscreen mode

Vary the 32768 to as large as you expect the response to be, but do limit it. Don't do unlimited reads from the network.

Overuse of init()

init() almost always implies globals. See next item.

Overuse of globals

This really applies to all programming languages, but when you have a global, it is probably a sign that you've designed the structure of your application poorly.

Early on in a project is the best time to spend time to avoid this.

Top comments (1)

Collapse
 
jrwren profile image
Jay R. Wren

More food for thought: fosstodon.org/@filippo@abyssdomain...