6 ms·
There's another good use for Makefiles with go. Gopath is one of the dumbest ideas I've seen. Multiple large projects under the same directory? Who thought tha
by rgbrenner 9y ago
There's another good use for Makefiles with go.
Gopath is one of the dumbest ideas I've seen. Multiple large projects under the same directory? Who thought that was a good idea. (and yes, I know you can create subdirectories, and mix all your packages together to create a giant mess.)
So I separate the projects into their own directories.. and use a Makefile to set gopath and run the go commands.
Still trying to figure out why golang tried to be innovative here.. What couldn't they use cwd like every other compiler I've ever seen?
- iainmerrick 9y agoI seem to recall hearing that was finally being fixed, but a quick search of the docs suggests not. I think it's just GOROOT (another bizarre idea) rather than GOPATH that's no longer strictly required in the latest version of Go. I agree with you, I don't understand why GOROOT couldn't just be the directory containing the compiler, and GOPATH couldn't just be the current directory. Maybe make me put some kind of workspace file there to identify it as the project root, that'd be fine.
- chimeracoder 9y ago> I seem to recall hearing that was finally being fixed, but a quick search of the docs suggests not. I think it's just GOROOT (another bizarre idea) rather than GOPATH that's no longer strictly required in the latest version of Go. GOPATH is set to `~/go` by default, and if your projects use vendoring (which they should), you can almost completely ignore that it exists. Packages in `./vendor/` will take precedence over anything in your GOPATH.
- iainmerrick 9y agoDo most Go programmers put all their code under ~/go, or do they tend to set GOPATH on a project-by-project basis?
- bacongobbler 9y agoMost put it under ~/go. It's quick and easy.
- foo101 9y agoMost set the GOPATH. It's quick and easy.
- clra 9y agoQuite a few current Go programmers will have something set other than `~/go` because that default only came in very recently, but you'll probably find that almost everyone uses `~/go` or `$GOPATH`. One thing that you learn quickly when starting Go is that fighting the language's idioms (even where they're questionable) isn't going to be a good time.
- iainmerrick 9y agoYeah, that's pretty much why I haven't learned Go. :)
- oelmekki 9y agoDon't know about others, but since I run my projects in containers anyway, I'll usually use `direnv` on my host to set GOPATH to project directory, and then use the default GOPATH in go docker images (`/go`). I could even do without direnv altogether, but I need it so that vim-go can report build errors on file saving.
- petepete 9y agoI use virtualgo[0] so I can organise my work properly and not mix my own stuff up with loads of unrelated libraries [0] https://github.com/getstream/vg https://github.com/getstream/vg
- baby 9y ago> if your projects use vendoring (which they should) For versioning? Also: 1. I haven't seen projects on github using vendoring 2. It doesn't look like `go get` allows you to download a package directly into your vendor file
- fpoling 9y agoFor my personal project [1] I use vendoring. But as of Go 1.8 it is still inconvenient as the main package has to be on GOPATH/GOROOT or the compiler will not find it. To maintain it I use git-subrepo [2], a very convenient tool to embed the code into own tree. [1] - https://github.com/ibukanov/ljdumpgo https://github.com/ibukanov/ljdumpgo [2] - https://github.com/ingydotnet/git-subrepo https://github.com/ingydotnet/git-subrepo
- kensey 9y agoHave a look at /coreos on GitHub -- flannel, dex and prometheus-operator all use vendoring, just looking at what's pinned. matchbox does also.
- baby 9y agoThanks for the examples! https://github.com/coreos/flannel/tree/master/vendor https://github.com/coreos/flannel/tree/master/vendor
- lobster_johnson 9y agoFor the Go tools to work consistently, your code has to be inside GOPATH, which means you cannot ignore it entirely. You can often use relative package names (e.g. "go test ./..."), but it breaks whenever you use absolute ones, and the Go toolchain is based on this assumption being true. My experience is that editor plugins (e.g. the Go plugin for VSCode) don't like this. I use hardlinks (the "hln" third-party utility on macOS) to get around this, which means I can have all my projects under a sane directory structure under ~/Projects.
- insertnickname 9y agoPerhaps Dave Cheney's gb would interest you; it does not use GOPATH. https://getgb.io/ https://getgb.io/
- vbernat 9y agoIt is also my biggest gripe with Go and it's not quite easy to workaround. I am using a Makefile approach for that: https://vincent.bernat.im/en/blog/2017-makefile-build-golang https://vincent.bernat.im/en/blog/2017-makefile-build-golang
- leggomylibro 9y agoYeah, that is what turned me off of Golang. It was kind of a "straw that broke the camel's back" thing, though. Go is just an EXTREMELY opinionated language, and if you don't like that then you won't like it. The Best Way to do everything is decided for you ahead of time, which irks me because it isn't always true. But I can see the frustration it grew from when I use a language like Ruby, which has a half-dozen nearly-identical ways to accomplish most simple tasks. Anyways, you could muck around with symlinks and crap, but come on. If I can't simply mkdir/vim/compile/run a 'hello world' program, there's probably something wrong with the language.
- weberc2 9y ago> If I can't simply mkdir/vim/compile/run a 'hello world' program, there's probably something wrong with the language. Like this? `cat $HELLO_WORLD_PROG > /tmp/hello.go && go run /tmp/hello.go`
- leggomylibro 9y agoYeah, like that! But you know what I mean; multiple scattered workspaces, project folders on removable storage, etc. That sort of thing should be painless.
- weberc2 9y agoI've definitely had some other minor pain points with GOPATH, and I hate when veteran users of another language trivialize my pain points with their language, but I think all of the use cases you've described are all well within GOPATH's wheelhouse: export GOPATH=$HOME/go:/media/USB-DISK:/foo/bar/baz Now Go can find any projects in any of those workspaces. The only caveat is the projects have to be in a workspace, which is a directory with a src folder containing your project. I agree that this is a minor nuisance and I would design it differently, but Go's tooling is still far easier than pretty much anyone else's (it's actually what brought me to Go).
- vog 9y ago
- hgl 9y agoYou can work around the GOPATH issue by using Docker. If you build go within a Docker container, you can structure the folder however you like and it won't affect the host. The only downside is that your text editor might stop offering some features when editing a go file, since the import paths might not point to the actual location.
- grogenaut 9y agoThe only downside being well having to use docker to work in a modern language
- shriek 9y agoI don't think you have to go that far. I think something like https://direnv.net/ https://direnv.net/ should work too. Although, I do agree that having this restriction in the first place is bizarre.
- iambvk 9y agoAfter struggling a lot, I think, I finally understood best use for GOPATH with Makefile based projects. I use it as follows: I have ~/go for all 3rd party code that I did not develop. My personal projects live in a different directory with a different structure (including, configure.ac, Makefile.am, etc.). My projects tend to use multiple languages, so I need Makefile support. I fix GOPATH in project specific Makefiles with ~/go as the first directory followed by project specific directory for Go code. For example, I add the following in Makefile.am of every project. GOPATH := $(HOME)/go:$(CURDIR)/go One cool result of this is: When I do go-get of any 3rd party package (either through command-line or as part of a rule from Makefiles), Go downloads them into ~/go directory (it picks the first directory in GOPATH or defaults to ~/go). This leaves my project specific directories free of 3rd party code -- which is what I want. End result is, ~/go ends up with 3rd party code from across all projects and it doesn't include my project code, so can be deleted any time and re-created automatically by Makefile rules.
- bkeroack 9y agoWhenever someone says "X is one of the dumbest ideas" there are two possibilities: 1. The person who came up with the idea is actually very stupid. 2. The person speaking doesn't fully understand the idea, or all applications of it. Guess which option is more commonly true?
- iainmerrick 9y agoQuite often it's just 3. They're obviously exaggerating, but still onto something. Why is GOPATH a good idea? Can you explain it? I guess the intention is to have all the packages you're using side-by-side (including the one you're working on)? That is not obviously a terrible idea, but as Go has more recently adding vendoring support, it clearly doesn't cover all the use cases. If I'm using a third-party package, I almost always want to either install it in /usr/local (via Homebrew, say) for minimal hassle or vendor it into my project so the project is standalone. The GOPATH approach -- having external packages as peers of my project -- feels like a pretty distant third (although admittedly I'm not a Go user). This feedback was given very early on in the development of Go, so the GOPATH behavior could easily have been changed, but clearly the language designers felt it was a good approach. I imagine it's a Plan 9 convention?
- slrz 9y agoI don't understand the GOPATH criticism. For your C compiler to find included header files they need to be specified relative to /usr/include (or some other path contained in the list searched by your compiler). For the go build tool to find Go packages they need to be given relative to (an element of) GOPATH (which is a colon-separated list of directories that is searched for Go package sources). To work on your own code inside your home directory while installing other packages using Homebrew, you'd set a GOPATH of $HOME:/usr/local. If you also want to consider packages shipped with the OS, you append a ":/usr" to that. Lots of things work this way: @INC in Perl, sys.path in Python and many more. Why have people such issues understanding this concept when it's called GOPATH?
- iainmerrick 9y ago
- fortythirteen 9y agoI believe the idea behind it is that you should only deploy one app per container. Perhaps developing locally with Kubernetes would be a simpler path.
- zaphar 9y agoGOPATH exists to tell the go tool where to find the libraries that go get installs. You can have multiple GOPATH entries in there if you want to segregate things. It's basically PYTHONPATH with a few extra bits. One of the reasons is that many of the developers of Go subscribe to a monorepo philosophy. GOPATH enables and encourages that practice.
- sethammons 9y ago> Multiple large projects under the same directory Sorry to be snarky, but everything, eventually, is under one directory. "/". There seems to be two kinds of folks working with Go: those who want to do it their way, and those who want to do it the Go way. I'm in the latter group. > ... I separate the projects into their own directories So do I, but I just don't get to pick that directory. Everything is in $GOPATH. $GOPATH/src/github.com/:org/:package is my directory for any given project. That project has a /vendor directory with its dependencies. Everything is contained within my project's directory. It is in source control. Everything just works with the Go tooling. > ... use a Makefile to set gopath ... If you don't fight the system, you don't need to set GOPATH per project. I totally get there is something that maybe I just don't understand or am totally missing, but in _years_ of working with Go on many dozens of applications, I've never had to alter my GOPATH (aside from the one application that a team at our company did where they put their source control at the $GOPATH/src directory, which was a pain in the butt and is not the way to do things). > Still trying to figure out why golang tried to be innovative here... Yeah, it was weird for me at first. I accepted it as the way of things and my life got better. And to harken more back to the heart of the thread: makefiles. While I just don't understand the need for separate GOPATHs, I can see some value for complicated build or test commands. For the most part, `go test -race` and `go build` is what I need 90% of the time. Mostly, it is the build system that needs the equivalent of `make test` and `make build` to ensure flags are set and such.