Hacker News new | ask | show | jobs
by brandur 2810 days ago
A few years into using Go, I have mixed feelings about `GOPATH`. On one hand, I can see the author's frustration in that it was always incredibly presumptuous of the language's authors to dictate how its users should organize their hard drives, and more so it feels like exactly the type of arrogance that people tend to attribute to the Go's core and community.

Also, having helped a number of people now through their early days of the language it's also the one biggest thing by far that reliably confuses every single person. And I mean everyone — from first time programmers all the way up to people who've been in the industry for decades and are learning Go as their tenth language. Being forced to put files in certain places is incredibly non-intuitive because there's nothing else out there that requires it. I must have sent the Go documentation on workspaces [1] to two dozen different people at this point.

But on the other hand, once you've grasped the system and are using it, `GOPATH` is surprisingly not bad. It's always obvious where your dependencies are located and which versions are going to be used to build your project. Even better, it lets you very easily drop into those dependencies and add minor changes or debugging lines if you need to. This can be incredibly useful if you're trying to understand how one of them works or think that that you might have found a bug and trying to verify or patch it. A very powerful feature once you know about it.

The new Go modules seem good, and will be a huge improvement in lowering the barrier to entry for Go, but I'll miss the old `GOPATH` style of work at this point.

[1] https://golang.org/doc/code.html#Workspaces

4 comments

There's going to be a large group of people (myself included) who graps the system but refuses to use it because it's pointless and stupid.

> It's always obvious where your dependencies are located and which versions are going to be used to build your project.

More obvious than specifying the version in some dependencies file?

> Even better, it lets use very easily drop into those dependencies and add minor changes or debugging lines if you need to.

What dependency management system doesn't allow you to do this if you insist?

> More obvious than specifying the version in some dependencies file?

I have nothing against dependency files, but yes, it's probably even more obvious.

If I see an `import "github.com/x/y"` at the top of a Go file, I know that I can go find the source for that at `cd $GOPATH/src/github.com/x/y` (unless the project has a `vendor` directory in which case you'll look in there instead).

> What dependency management system doesn't allow you to do this if you insist?

I'm sure you could do it on anything, but Go makes it very easy.

As noted upthread, it's pretty simple to do this in other languages like Ruby when you're using Bundler and know the system well (e.g., `pushd $(bundle show excon)`), but in many languages it's much more difficult. You'd need to go chase down the source, download it, then redirect your dependency to point to it. Sometimes you'll grabbed a newer version that's no longer compatible so you'll have to make sure to work off of the right tag.

In bad cases (e.g., C, Java) you'd have to learn how to build the project which might not be trivial because tooling isn't standardized or convenient to use.

> What dependency management system doesn't allow you to do this if you insist?

Dependency management systems that require you to hunt for where they stashed whatever they sucked down based on the versions you listed in some file might, in some cases, make this particular task more complex than it strictly needs to be.

> Even better, it lets use very easily drop into those dependencies and add minor changes or debugging lines if you need to.

I've done this quite a bit with typical Ruby+bundler setups. I think the key is that both Go and Ruby start from source code, vs. something like Java where your dependencies are compiled JARs without source (of course, there is infrastructure to enable easy fetching of the source when available).

This is similar to my experience with Nix package manager. It's purely source-based with binary packages seen as something like a compiler cache. It's easy to get the source to a package, make some tweaks, and build (and use) a custom version (at least I personally have found it far easier than Debian, even with apt making it easy to get the source).

> Even better, it lets you very easily drop into those dependencies and add minor changes or debugging lines if you need to. This can be incredibly useful if you're trying to understand how one of them works or think that that you might have found a bug and trying to verify or patch it.

You should totally check out Roger Peppe's gohack[1] It enables you to do the same in a Go modules world

https://github.com/rogpeppe/gohack

As someone who hasn't used Go, it sounds like GOPATH is very similar to an Eclipse IDE Workspace.
Now you mention it, it sorta is; I haven't used eclipse, but I've never stopped putting all of my projects into a single folder called "workspace" in my home directory.

The main difference would be that all dependencies are also in this folder, instead of e.g. a maven or ivy folder located somewhere else. And a (suggested?) folder structure, not dissimilar to java's package structure, where you'd put your e.g. github.com/user/repo repository into $GOPATH/src/github.com/user/repo. I'm sure there's clever tooling or commandline wizardry that works really well with a structure like that.