
Setup for Your Next Golang Project - MartinHeinz
https://martinheinz.dev/blog/5
======
divan
Setup for your next Golang project should be an empty "main.go". Let the
project grow naturally.

~~~
_wldu
Yep, and a standard Makefile too.

~~~
monocasa
What's wrong with starting out using go build, go run, and go test?

~~~
pstuart
Nothing at all. But the moment you move past that it's a nice standard way of
encapsulating tasks related to the project.

~~~
monocasa
So there's no need to start with that is the point.

~~~
tedunangst
Faster to type make than go build.

~~~
divan

      alias b='go build'
    

`b` is even faster to type :)

------
grammarxcore
I think it's important to note that this is a very opinionated way to set up
Golang projects. It relies on a lot of tooling not explained in the post plus
uses some processes that may or may not be standard (eg the version is one of
many ways to do it). In future posts you might want to break down why you do
things the way you do and explain why you chose those solutions over others.

For those interested in skipping initial page (which seems to be insanely
slow), just check out the boilerplate repo:
[https://github.com/MartinHeinz/go-project-
blueprint](https://github.com/MartinHeinz/go-project-blueprint)

~~~
MartinHeinz
You are right, this is quite opinionated solution, as everybody has their
preferred ways of coding. The fact that not everything is explained in this
post is because there are 4 parts, which are all linked at the top of README
in the repo you linked.

The pages loads quite slow indeed, that's because of the traffic coming in
right now... The 1GB RAM VM is having hard time serving all the requests...

~~~
ben0x539
Do you think it might be worth it to prod a moderator to change the URL of
this submission to [https://towardsdatascience.com/ultimate-setup-for-your-
next-...](https://towardsdatascience.com/ultimate-setup-for-your-next-golang-
project-1cc989ad2a96)?

------
jen20
I would hardly say this structure looks "perfect". For a start:

\- Use of Docker is a serious problem. I have no intention of ever running
Docker on my machine to build some random project for which I have the
toolchain already installed. Wrapping Docker with a Makefile is even more
irritating.

\- Use of "package pkg" to keep the version number in is bizarre - I've never
seen that before. Some use `package version` _inside_ a `pkg` directory which
contains other public packages also, and use of `package version` at the top
level is also fairly common.

\- Multiple modules in one git repository presents many challenges for people
who want to reference them at different commits in other projects.

\- `pkg app` under a `cmd` directory is sometimes fine, but if there is only
one app and no library, keeping it in the root should be preferred so that `go
get` works properly. Furthermore, other packages being nested under it is not
often great, since they are highly likely to be reused by other `cmd`s in the
same repository.

Personally for Go I've never needed a "starter" project, since not much needs
configuring out the box as the toolchain is quite reasonable.

If I were evaluating a project structured like this as a potential dependency,
I'd knock off major marks for the structure and investigate alternatives. I
guess if things came down to the wire, the structure wouldn't be a deal
breaker, but I'd certainly aim to avoid it.

------
throwaway894345
> People often say "It works on my machine (and not in cloud)...", to avoid
> this we have simple solution - always run in docker container. And when I
> say always I really mean it - build in container, run in container, test in
> container. Actually I didn't mention it in previous section, but the make
> test really is "just" docker run.

I've had nothing but bad luck with Docker for Mac. It's been super slow. If
any container is running at all, the com.docker.hyperkit process eats 160% CPU
even if `docker stats` shows the process hovering near 0% CPU. This has been
the case for our entire team, and we're in the process of moving away from it.

~~~
sebazzz
Docker, it works on my machine.

\---

But to add a serious note, why is every dependency on the environment so
complicated that we just wrap it in some container to just get rid of it?

~~~
throwaway894345
> But to add a serious note, why is every dependency on the environment so
> complicated that we just wrap it in some container to just get rid of it?

Bad build/dependency-management tooling and non-perfect abstractions over
system APIs probably account for most of the issue.

Containers are conceptually useful; it's nice to have ephemeral, isolated
environments. But if it literally eats all of the CPU it can get its hands on,
then it's not useful.

------
stevehiehn
Hmm, interesting I had assumed /cmd/ was used for cli-ish applications that
use a 'command pattern'. I didn't think people also did this for http apis.

~~~
tptacek
That is my understanding as well, and having a directory tree that goes like
"projectname/cmd/projectlibrary" seems super weird and non-idiomatic to me.

~~~
herval
pkg/cmd or just /cmd are rather popular in a lot of projects
([https://github.com/grafana/grafana/tree/master/pkg/cmd](https://github.com/grafana/grafana/tree/master/pkg/cmd)
/
[https://github.com/prometheus/prometheus/tree/master/cmd](https://github.com/prometheus/prometheus/tree/master/cmd)
/
[https://github.com/istio/istio/tree/c3e1824c5e3f3e51ceb4a80b...](https://github.com/istio/istio/tree/c3e1824c5e3f3e51ceb4a80b46aee9876be07131/istioctl/cmd)
/
[https://github.com/containous/traefik/tree/master/cmd](https://github.com/containous/traefik/tree/master/cmd)
/ etc)

~~~
tptacek
cmd/ directories are normal. Hosting all the business logic for the whole
package _under_ cmd/ seems less normal.

You kind of _need_ cmd/, because you can only have one main() in a package,
and a package with a main() can't easily be imported into another package.
That's why the directory exists, not (as I understand it) because there is
some merit to burying code 3 directory levels deep.

~~~
herval
my response was to your comment that "having a directory tree that goes like
"projectname/cmd/projectlibrary" seems super weird and non-idiomatic to me"

~~~
PhilippGille
I'm on mobile and didn't check all your examples, but grafana has pkg/cmd and
traefik has cmd _next to_ pkg. That's not having the business logic below cmd.
Whereas cmd/pkg is.

------
thiht
> People often say "It works on my machine (and not in cloud)..."

That's definitely not a problem I have with Go. Building everything with
Docker is wayyy overkill.

Also, why is everything under the cmd/ package? It doesn't make sense.

As for go modules, using `mod vendor` might not be the best suggestion as it
requires using `go build -mod=vendor`. If you use go modules, just use go get
and drop the vendor folder.

------
bdibs
For comparison, here's a popular standard:

[https://github.com/golang-standards/project-
layout](https://github.com/golang-standards/project-layout)

~~~
sagichmal
It's neither necessarily popular nor standard. Despite the GitHub org name
they have no particular accreditation from anyone.

~~~
andyroid
11.8k stars on GitHub doesn’t qualify as popular?

------
michaelperel
(Shameless plug): For those looking for a good dev container experience with
VSCode that works with go modules: [https://github.com/michaelperel/docker-
lock#development](https://github.com/michaelperel/docker-lock#development)

edit -- on mobile, scroll down to "development"

------
xealgo
I use the cmd directory for my main files, setups, etc... but use project root
level packages for the bulk of the business logic. I kinda go the impression
here that he uses cmd for all source.

------
dschulz
Thanks for sharing. I've been perusing your blog posts and GitHub repositories
for a week or so. Very useful stuff :)

------
mrinfinite
page loads slow, so i cancelled trying to open this link.

~~~
jturpin
Not only that but it seems to be loading the same HTML content 3 times.

