

Application Development in Go - jameskilton
http://jasonroelofs.com/2013/08/01/application-development-in-go/

======
BarkMore
Although the author touches on some real issues with writing applications in
Go, I do not recommend this article. The author does not follow the
recommended practice for writing Go applications and the author has
misconceptions about the Go tools.

 _a developer can not expect anyone to individually go get 20-plus different
packages_

Because the 'go get' command fetches dependencies recursively, there's no need
to 'go get' packages individually.

 _the developer is forced to remember which packages the application uses, and
which are other projects_

The 'go list' command will tell you the dependencies for an application: go
list -f '{{.Deps}}' path/to/application

 _For Slartibartfast I decided to give this project its own Workspace, with
its own $GOPATH, and put the entire Workspace into git._

This is not the recommended practice.

 _each package is expected to be in its own source repository_

A repository can contain more than one package. There's no requirement that a
package exist in a repository.

 _go get probably works great for the needs inside of Google_

Google does not use 'go get' internally.

 _anything placed in the src /[package] directory gets compiled into the
resulting binary_

Go files matching the build tags are compiled into the resulting binary.
Everything else is ignored, including Go files that don't match the build
tags.

That's enough nitpicking. The take away that I get from reading this article
is that "How to Write Go Code"
([http://golang.org/doc/code.html](http://golang.org/doc/code.html)) needs
improvement. The document was overhauled earlier this year to make it easier
to understand. Apparently, it's not easy enough.

~~~
corresation
Articles like this -- even if they have errors or arguable non-best-practices
-- should be recommended because they drive conversation. Thus far one of the
most unfortunate things I've noticed about the Go community (and this is seen
even in discussions about Go on here) is a silence that results from a fear of
doing things wrong. That improves no one.

 _The 'go list' command will tell you the dependencies for an application._

Does it? I thought it simply showed every package in the application, not
differentiating what is yours and what is not. If I am correct, in no way does
it solve the problem that they were trying to address.

 _This is not the recommended practice._

They specifically note that it isn't the recommended practice, but that it was
a compromise to make a more easily reproducible structure. It _is_ absolutely
odd -- from a traditional developer perspective -- how the structure of a go
application works when there are many dependencies, and I'm not sure what _is_
the recommended practice for actually source controlling that (though we know
how individual packages should be managed).

 _Go files matching the build tags are compiled into the resulting binary_

Can you describe what you means? Such as

go build _github.com /mypackage_?

I've built several solutions with Go now and remain sure that much of what I'm
doing is wrong, despite trying to find the relevant information.

~~~
dragonwriter
> > The 'go list' command will tell you the dependencies for an application.

> Does it? I thought it simply showed every package in the application, not
> differentiating what is yours and what is not.

How is that _not_ telling you the dependencies for an application? And
differentiating yours from others ought to be trivial if you use the
recommended directory structure with the path under /src corresponding to
repository locations.

~~~
corresation
Many real applications consist of tens to hundreds of packages, tens to
hundreds which might be in development in the application, and tens to
hundreds which might be dependencies.

I fail to see how following the recommended directory structure (which is
_assumed_ ) helps that, beyond that you can then correlate with a separate
list of "things that are mine".

In a Visual Studio project, just to bring up a comparative example, I have my
solution and projects. And then, elsewhere, I have nuget dependencies. There
is absolutely no question which is which (nor is there any confusion on how to
source control the whole, including that the dependencies include nothing more
than pointers to their location/version). In my go project there are hundreds
of seeming equals.

~~~
dragonwriter
> I fail to see how following the recommended directory structure (which is
> assumed) helps that, beyond that you can then correlate with a separate list
> of "things that are mine".

If you are following the recommended directory structure, you don't need to
"correlate" to "a list" of things that are yours, as all of your things will
be under a path that corresponds to your remote repository, while external
dependencies will be under paths that correspond to other remote repositories.

> In a Visual Studio project, just to bring up a comparative example, I have
> my solution and projects. And then, elsewhere, I have nuget dependencies.

In Go, you have the solutions and packages under (e.g.)

    
    
      /src/github.com/corresation/
    

And then, elswhere, you have dependencies that aren't yours.

------
grey-area
_First, a developer can not expect anyone to individually go get 20-plus
different packages (Slartibartfast has more than 10 and growing), not to
mention whatever 3rd party dependencies the application uses, to work on a
single application._

go get fetches dependencies, so this is not an issue with go get, anything
imported will be fetched.

 _There is no place to put such resources in the normal Go Workspace, as
anything placed in the src /[package] directory gets compiled into the
resulting binary and is not accessible or editable from outside._

It's quite possible to put resources into a go pkg folder without causing
problems, and those are go gettable along with the code. I don't see the issue
here.

 _Running go get for a package clones the repository at its current HEAD
/master/trunk, with no way of specifying a version or commit you might want._

Go get doesn't (yet) get versions of packages, just fetches the master. This
is something that's been discussed to death on the mailing list, there are
plenty of threads:

[https://groups.google.com/forum/#!forum/golang-
nuts](https://groups.google.com/forum/#!forum/golang-nuts)

Some solutions to that are:

Go get everything once, and then stop using go get (the solution in the
article, though he brings workspaces into it too, which is unnecessary) - this
is problematic as he points out.

Put all your dependencies into subpackages, frozen at a particular version, I
like this solution for now.

Put all your dependencies into your own repo, again frozen at a particular
version, and only go get or checkout from there

Use something like gonuts.io to add versioning information (relies on the pkg
authors to do this though)

Add versioning to go get to check out versions to a specific path.

It would actually be pretty easy to add version dependencies to Go by adapting
the go get source. go get already versions for version of the _language_ by
looking for a certain tag, but not versions of the package. You could just
check out to a path like src/github.com/jasonroelofs/slartibartfast/1.0/ and
use that path for imports. Someone should just go ahead and do it, to see how
it works out - if it's popular, people will use it, and eventually it might
make its way into the default distribution. The folks at Google just don't
seem to see it as a problem so presumably their setup/usage doesn't hit this
problem.

~~~
jjindev
My fantasy vision, predating go, was publisher/project/version with /src and
/bin below all that (separate bins and srcs). I am open to re-balancing that
tree ;-), but somewhat surprised that version wasn't in from the beginning.
Perhaps there were more worms in that can that I expected. (version should be
constrained to x.y.z numeric form)

~~~
grey-area
_My fantasy vision, predating go, was publisher /project/version with /src and
/bin _

Yes in a way that feels more natural to me too - all your stuff is in one
place, including src and binaries, not mixed up with other binaries/source and
all under one version. The current scheme does follow unix conventions though
and it's not too important.

The only persuasive criticism I've seen of versioning is that it doesn't deal
with dependency hell automatically, however I'm not sure it can or should, and
having simple versioning would be a nice step up from simply checking out
master at the time you happen to go get, which means go get is not a reliable
tool for fetching dependencies if you don't freeze them somehow (hence the
contortions of this developer). It's not a huge deal though, and I'm sure
it'll be addressed somehow at some point and the meantime there are various
possible workarounds.

------
tyleregeto
We use per-project work spaces too and it has simplified a lot of things for
us. The biggest reason for this is that our projects aren't just Go based,
their are other languages in there, many different file types. Building the
project doesn't mean running "go build", that's just one component of a much
larger code base. A complete build for a web application means:

* compile the Go app

* compiling the Sass files down to CSS

* combining and minifying Javascript files

* minifying HTML files

* optimizing/compressing image assets

* etc.

These things need to happen together, and than are organized into the
deployable file structure. Ofcourse this is all automated with scripts, but a
single global Go workspace doesn't cut it. It assumes that the Go app is king,
while in reality its just another component.

------
evmar
An easier approach to the submodule problem is to use "git subtree" to copy in
any dependencies of the project into your tree. Then (1) your project always
builds against exactly the version of the dependency you tested against, and
(2) if someone else deletes their repo it doesn't affect your project (unlike
git submodules).

~~~
eknkc
What if my dependency depends on something else and that something else breaks
things when it's updated? Is there a decent way to lock all dependencies
recursively?

------
riobard
I have similar problems building Go apps for internal use. My solution so far
is to use per-project $GOPATH and `git subtree` to manage the whole $GOPATH as
a single repository.

The primary benefit of doing so is build repeatability: any dev can `git
clone` the repo and build the app successfully after setting the $GOPATH to
the repo directory. Changes in external dependencies have no affect on us
until we manually incorporate them into our repo via `git subtree`. There is
no need to `go get` and we avoid its associated problems (e.g. versioning,
availability of remote repos, etc).

------
jjindev
It seems the go team chose a method that would produce zero name collisions
under parallel development. That's the highest goal, but of course the burden
of it is that paths below /src must be kinda long to support it. A "rare
collision" solution could have been more concise without being as robust.

~~~
freyr
A common theme in Go is "Do important things the correct way," even if that
equates to slightly more work for the developer.

People will inevitably argue about (a) what's really important, and (b) what's
really the correct way. But they didn't create Go. It's clear where Go's
creator stand on the issues.

~~~
jjindev
I had a funny experience. Before I ever worked with Go a developer I'd worked
with (and argued small details and big philosophies), told me "why don't you
use Go? It seems your kind of language." From my later glances it seems like
he was right. So I might be in the fortunate subset for which the philosophy
matches, more or less.

