
What I learned in 2017 writing Go - zeveb
https://www.commandercoriander.net/blog/2017/12/31/writing-go/
======
payne92
_> > ...a careless approach to a main function can result in needless
complexity. Compare two versions of the same main function: before and after.
One version is over 400 lines. The other is about 40 lines. That’s an order of
magnitude. One will be easy to change._

A potentially contrarian view: a long-ish straight linear function without
duplicated code is often much easier to understand than a smaller function
broken into subroutine callouts (because you don't have to chase down the
implementation of the subroutines to figure out what's going on).

~~~
haberman
While I tend to agree with this, I think a counterargument is: long functions
mean more local variables that are in scope. This makes it harder to
understand the interaction between different variables at different scopes. A
separate function introduces a separate namespace, and all the data flow in
and out has to be explicit, through function parameters/returns.

~~~
Waterluvian
I would love an IDE that unrolls subroutine calls inline as a view mode.

~~~
WaxProlix
Peek definition does this, sort of. Definitely exists in VS and VS Code, and
probably in the JetBrains things.

------
krylon
I concur on gometalinter.

It can be a pain sometimes to satisfy it, but most of the time, my code ends
up better than it was before.

Well, except for gocyclo. Some functions just _are_ complex - simplifying them
or breaking them up into several smaller functions just to keep each function
small is not always the best idea or even possible. But that can easily be
disabled on a per-function basis.

------
lclarkmichalek
The `pkg` package is a horrible convention. Having a `cmd` directory makes
sense, as each binary needs to be a separate package, but putting all your
libraries under a `pkg` directory is unneeded.

~~~
013a
I hate the pattern primarily because it overloads the name "pkg" which is
already used in your go workspace at least one directory up to store compiled
library files.

The word "lib" makes more sense. But, also, its unnecessary.

~~~
jdc0589
I've always used `lib` in every other language. I see no reason to change....

------
it
Delve's main doesn't seem all that exemplary. It's irritating to open up main
only to find that the princess is in another castle.

------
tschellenbach
For dependency management we use Dep
([https://github.com/golang/dep](https://github.com/golang/dep)) combined with
([https://github.com/getstream/vg](https://github.com/getstream/vg)). This
works pretty well.

~~~
raziel2p
I didn't know about vg and it looked promising, but I was disappointed to see
that it still requires that I initialize all my projects in a subdirectory of
$GOPATH/src. Why does go (and/or its tools) enforce this? Why can't I put my
projects in ~/code? Why do I need a "github.com" subdirectory? Feels so silly.

~~~
JelteF
Main developer of vg here. In principle vg should work for packages outside of
GOPATH when using full isolation mode (which has its own set of problem, see
README for details). Its dep integration doesn't work then though last time I
tried. As far as I can tell the main reason why Go tooling needs GOPATH is
because everything uses absolute imports and relative ones can translated to
absolute ones by always working from inside the workspace.

I've solved my main issue with GOPATH in a very easy way though. I just create
symlinks in my normal directories (like ~/work) to my projects in GOPATH. This
allows me to go to my own projects easily while still having everything in
GOPATH.

~~~
collinvandyck76
I use zsh and there is an easy way to find your golang projects using cdpath:

    
    
        # setup easy access to cd paths
        
        setopt auto_cd
        cdpath=($HOME/code/go/src/github.com \
          $HOME/code/go/src/github.com/collinvandyck \
          $HOME/code \
          $HOME/code/go/src)

------
LanceH
How do people differentiate between packages being worked on and packages
installed?

Let's say I have my-package (version 1.0) installed and in use in a lot of my
other projects. But I'm working on version 1.1, but need to have 1.0 as the
reference for other projects.

Right now I just fiddle with $GOPATH but that feels like a hack and is an
annoyance if I have to swap around a bit.

Right now my-package might be in a broken state because I'm working on it, so
I can't build anything relying on it if I go with the single $GOPATH hierarchy
that every discussion seems to assume.

~~~
bigdubs
Generally we use vendoring, i.e. you have 1.1 in your gopath, but vendor 1.0
in your projects (as long as they're standalone projects).

It's also important to limit cross package dependencies as much as possible to
avoid these situations.

~~~
rocmcd
Yes, vendoring is the best choice here. I'd also recommend everyone give
dep[1] a shot.

[1] [https://github.com/golang/dep](https://github.com/golang/dep)

~~~
m90
Having tried to migrate from godep to dep a couple of times now I always gave
up seeing how many additional unneeded files dep will pull into my /vendor
folder.

Just a few days ago using dep instead of godep on a medium-sized web
application gave me a delta of 1,920,834 additions and 1,942 deletions
(_after_ manually pruning _test files), mostly caused by depending on aws-sdk-
go.

Do you have any strategy for keeping your vendor small with dep or do you just
accept it the way it is?

There seems to be this:
[https://github.com/golang/dep/issues/858](https://github.com/golang/dep/issues/858)
, but it looks like it's not implemented yet and the status is highly unclear.

~~~
JelteF
Running "dep prune" after "dep ensure" should remove a lot of unnecessary
files (this will be integrated into ensure somewhat soon). Also, in a lot of
cases it's not needed to commit the vendor directory, so its size doesn't
really matter then. Finally, I really recommend checking out the #vendor
channel on the Go slack if you have any more questions regarding dep, everyone
there is really helpful.

~~~
m90
Do you have production applications running that do exclude their vendor
folder? Does this work reliably? How do you handle dependencies that do not
use semver?

What would be one of the cases where you'd say you need to commit vendor?

~~~
JelteF
All our production applications don't have their vendor committed. By running
"dep ensure" it dep restores the exact same vendor directory from the lock
file, we do this in CI where we build our binaries. For dependencies that
don't support semver dep uses the master branch by default and pins a commit
to support reproducible builds. The only case where this has caused problems
for us was when one of our dependencies force pushed to master, so the commit
that was pinned didn't exist anymore. This resulted in a failing build though,
not an inconsistent one.

Other than working around that issue the only case where you actually need to
commit vendor (at the moment) is when you want your project to compile
reproducibly by only running "go get project". If you are fine with telling
your user to run "dep ensure" (or make) first this is not needed. This is not
usually an issue when working with colleagues, but can be nice for publicly
released projects.

~~~
m90
Thanks for all the insights! I will give this a go soon I guess.

------
Dirlewanger
This is coming from a comparatively spoiled Rails developer, but: why would
anyone bother using a language in production if it lacks fundamental things
taken for granted like dependency management and stable testing
frameworks/practices? Do people just not do enough due diligence and get
blinded by a language's honeymoon period?

~~~
rufugee
You realize that bundler isn't a part of Ruby, correct? You're comparing
apples to oranges.

~~~
LukaD
Does Go have a comparable tool that is as widely adopted as Bundler is?

~~~
collinvandyck76
It looks like `dep` will be this tool for Go.

