
Hellogopher – Just “git clone” and “make” any Go project - FiloSottile
https://github.com/cloudflare/hellogopher/blob/master/README.md
======
Ruphin
Projects like these and their popularity are indicative of how unapproachable
the Go development environment is to new users. One of the first things I did
when introducing Go at work is write a bunch of script that solved this exact
issue for our team, and I suspect that a solution like this has been written a
million times over already.

I love the Go language but the development environment tooling is just awful
(aside from some great things like gofmt). This requirement of having files in
specific folders to be able to build, the (lack of a sane) vendoring system,
both problems keep popping up and spawning new solutions over and over. There
is no excuse for a modern language to force people to learn how to use the
tools before they can even start using the language. Tools should work for the
user, not the other way around. Other languages get this right, so why can't
Go?

Kudos to the author for spending some time to document and publish their
solution to this specific issue. If these projects get enough traction, like
govendor, perhaps the language authors will at some point incorporate the most
popular solutions into the language platform. At least it'll save everyone
else from rewriting the same tool.

~~~
FiloSottile
Then you'll be happy to hear that part of Russ Cox's 2017 resolutions [0] is
to make the go tool work without GOPATH (worded in a way that essentially
matches the hellogopher motto), and there's a nice proposal in that sense [1].

Moreover, an integrated package management tool to build the vendor folder is
coming soon [2]. We're getting there, now that the problem is getting more
understood!

[0]: [https://research.swtch.com/go2017](https://research.swtch.com/go2017)

[1]:
[https://github.com/golang/go/issues/17271](https://github.com/golang/go/issues/17271)

[2]: [https://blog.gopheracademy.com/advent-2016/saga-go-
dependenc...](https://blog.gopheracademy.com/advent-2016/saga-go-dependency-
management/)

~~~
stouset
Why is go so late to the party on this? Other languages do not seem to have
these kinds of problems.

The more I experience go, the more I feel like the core team existed in a
bubble away from the past 25 years of advancement in programming languages.
They're stuck solving the problems they had with C, without the benefit of
learning from or improving on any other modern languages or toolsets.

------
FiloSottile
Hey all, author here. Happy to take any feedback, in particular “I tried and
it didn’t work out of the box” stories. I will NOT tell you to RTFM.

I recommend reading
[https://github.com/cloudflare/hellogopher#why](https://github.com/cloudflare/hellogopher#why)
for more insight.

There’s also a gif demo
[https://twitter.com/FiloSottile/status/822745605806112768](https://twitter.com/FiloSottile/status/822745605806112768)

EDIT: uploaded the keynote I gave at Golab where I present the problem and
introduce this project
[https://vimeo.com/200469720](https://vimeo.com/200469720)

~~~
akavel
Am I right to understand that it's _" build from anywhere"_ as long as _"
anywhere"_ is not Windows? (Please don't tell me about MinGW/Cygwin if the
whole idea is to "make life simpler".)

~~~
FiloSottile
Sadly, correct.

There is no way a standalone tool couldn't reproduce this behavior on Windows,
and the eventual integrated solution definitely will, but it's just beyond the
scope of hellogopher and outside my expertise.

~~~
e12e
I'm also a little confused. This is a fix for the standard go installer on
platforms not setting a GOPATH, so that "go get" doesn't work without manually
configuring GOPATH?

Or does it actually do anything else (except "break" windows builds - or
rather introduce a system complementary to "got get" that isn't quite as cross
platform as go itself)?

~~~
FiloSottile
This is not about platforms (or about go get), this is about _users_ who don't
want to or know how to correctly use GOPATH.

It doesn't break anything, since you can still use go get, go build, or
anything that worked before. It doesn't _help_ Windows users, but it doesn't
hurt them.

~~~
kkirsche
But as of 1.8 there is a default gopath negating that

~~~
TheDong
A default gopath doesn't help a user who does "cd dev; git clone
[https://github.com/coolprojects/project;](https://github.com/coolprojects/project;)
cd project; go build" (or make)

The default gopath does not help there. Sure, if a user knows how to use go's
insane global-project-directory-bullshit then they don't need this, but since
it's a go-specific bullshit, they might not.

Every sane language lets you have a directory where you want for each
unrelated project. Only go dictates some crazy tree and defaults to creating
it for you in $HOME

~~~
e12e
Right. But in order to build a go project, you need the go compiler. And the
go compiler comes with "go get". So my question was more: if a user has
installed go (properly) should not "go get" be the sane, easy, one way to
install a project?

And isn't "fixing" "go get" better than adding a dependency on make?

(and I guess this project in a sense is a way to fix "go get", but it seems
thrasher fragile; any one project might end up with a broken makefile by
accident)..

------
nnx
The annoyance/confusion/hurdle of GOPATH for beginners in the language will
finally be resolved with the upcoming Go 1.8 release.

[https://beta.golang.org/doc/go1.8#gopath](https://beta.golang.org/doc/go1.8#gopath)

~~~
FiloSottile
The default GOPATH is great, but it only helps running "go get", it doesn't
solve developing in arbitrary locations on the filesystem. I address it at the
end of my introductory talk:
[https://vimeo.com/200469720](https://vimeo.com/200469720)

------
blablabla123
I think Go works very well without Makefiles. (IMHO even better) You can just
enter `go build .` You can install the stuff using your favorite package
manager, e.g. dpkg - then it's even possible to uninstall your stuff.

~~~
ctz
Thanks. Now I get a console full of:

    
    
      thing.go:10:2: cannot find package "whatever/thing/frob" in any of:
      	/usr/lib/go-1.7/src/whatever/thing/frob (from $GOROOT)
      	($GOPATH not set)
    

So I go looking for GOPATH documentation, and it tells me I need to put all my
source dependencies in one directory. That's unlike everything else on the
planet, but OK. I do that, and set GOPATH=~/go.

Now:

    
    
      thing.go:10:2: cannot find package "whatever/thing/frob" in any of:
      	/usr/lib/go-1.7/src/whatever/thing/frob (from $GOROOT)
      	/home/ctz/go/src/whatever/thing/frob (from $GOROOT)
      	($GOPATH not set)
    

OK, so do I need to set GOPATH as well?

    
    
      thing.go:4:2: cannot find package "bytes" in any of:
      	/home/ctz/go/src/bytes (from $GOROOT)
      	($GOPATH not set)
      thing.go:8:2: cannot find package "container/list" in any of:
      	/home/ctz/go/src/container/list (from $GOROOT)
      	($GOPATH not set)
    

That seems worse.

Now somebody teaches me about 'go get'. Great!

    
    
      package whatever/thing/frob: unrecognized import path "whatever/thing/frob" (import path does not begin with hostname)
    

(To be clear, I now can build all the golang code I want. This post is more
indicative of my experience getting started a few years ago. In my opinion,
GOPATH is a terrible design decision.)

~~~
blablabla123
You can check in your dependencies into vendors/, in case they are so complex.
However it's recommended to only have few dependencies.

Yes, you need to install your deps separately. (If the maintainer decides not
to use vendors/ and not check it into git) With C, the classic ./configure &&
make && make install also expects you to install your dependencies manually.
Using Go you have a canonical way to do it. Also if you don't plan to hack on
it, it's probably a got idea to go with binary packages. If there are none,
the tool is probably not exactly meant for production anyway.

------
verandaguy
As someone who's more fond of this approach than Go's native one, it's funny
how we've come full circle (even if this never gains widespread adoption).

Thank goodness for the inclusion of sensible vendoring, by the way! Go's
default system broke a lot of older code because of the native vendoring
system (if you can call it that).

------
drdaeman
Sorry, maybe this is a stupid question... but does this require me to store
all the dependencies under ./vendor in the repo?

I would really prefer it ./vendor would be .gitignored (like .virtualenv or
node_modules) and `make deps` would parse the source and fetch the deps, sort
of like `go get` does. Bundling all the dependencies in your own repo just
feels wrong to me. Especially if it's not git submodules (and I've heard
submodules are frowned upon by those who have tried them - I've haven't had
such necessity, so don't hold any opinion). At least very similar approaches
had led to some really bad experiences I had in early 2000's with PHP (it was
typical to bundle vendored deps there because of relative lack of package
management).

~~~
FiloSottile
That depends on the tool you want to use to manage your vendor folder, so no,
hellogopher does not enforce an opinion on that.

For example, you could modify the Makefile to run "gvt restore" before
building. However, I warmly recommend checking vendor/ in: not doing so
requires the user to have gvt (or whatever tool), breaks go get, and adds
unnecessary external dependencies (think left-pad).

More details here [https://github.com/FiloSottile/gvt#alternative-not-
checking-...](https://github.com/FiloSottile/gvt#alternative-not-checking-in-
vendored-source)

~~~
drdaeman
I see. Guess, bare `go get` just can't get a dependency into `./vendor/` so
either a third-party or checking in is required.

Is there any suggestions/best practices how to maintain `vendor/` under the
source control? I mean, handling updates, branch merges and all the disaster
that accidental local patches may bring - this sort of stuff?

~~~
TheDong
The real problem with go get here is that it can't pick a version, only
latest. Checking in vendor is much safer because your dependencies can't break
you.

there are no good upstream suggestions on how to deal with vendor.

My preference is to use to use [http://glide.sh/](http://glide.sh/) and store
'glide.yaml' and 'glide.lock' in the repo, at which point the vendor folder
can be recreated to the correct versions without needing to parse code or
checkin vendor.

Glide is also really good at handling updates, pulling from alternate sources,
tracking alternate branch names, etc etc.

------
weitzj
This looks awesome. I haven't tried it yet, but the hopefully it supports
writing test coverage files for multiple packages, i.e. I already split the
code up into separate packages and put each package in a corresponding
subfolder. Using go test ./... I want to collect coverage reports for all my
packages while ignoring `vendor`

So my workaround is something like the following, where I generate a coverage
report for each package to later concatenate them into a final coverage report

``` for i in $(go list ./... | grep -v 'vendor') do coverName="$(basename
$i).coverraw" go test --ldflags '-extldflags "-static"' -v -race
-coverprofile="${coverName}" "${i}" | tee -a "${test_outfile}" done```

~~~
FiloSottile
Just run "make cover" :)

It does exactly what you want, and it handles overlapping coverage blocks (if
two packages have tests that run the same portion of code), which just
concatenating will mess up. (It uses gocovmerge behind the scenes, but it will
be hidden from you.)

~~~
weitzj
Awesome!

It would be nice to include something like go2xunit so you can hook the
results up to the Jenkins coverage reports.

~~~
FiloSottile
We do that on the Cloudflare CI, but I deemed it too specific for hellogopher.
(I can be convinced otherwise.)

Instead, you run hellogopher with CI=1, and it drops logs and artifacts in
fixed locations, that you can then post-process as you like.

~~~
weitzj
Ah. OK. Yeah. That works as well for me. Thank you

------
codedokode
I also have spent some time to make bash scripts that would allow me to copy
my Go project into a temporary folder to linux machine and compile it.

------
djhworld
One thing that I really like about this is it makes building go things via
Homebrew that much easier, I've just been converting my tools and things I
install via a personal tap to use this - great effort!

------
justincormack
I have long used docker to build all my Go so I can put it where I wish, and
where makes sense for projects that are not all Go. Looking forward to a
permanent fix upstream eventually.

------
Sphax
I don't understand how HN ranks posts: this was at the very top with just 9
points, no comments, how does that work exactly ?

~~~
weitzj
If the post gets upvotes in a short amount of time it ranks higher

