Despite the confusing nomenclature, Go 1.11 finally added a proper package management system, which they called modules.
The first time I used Go I uttered a series of WTFs when I was told I had to put the code in a specific place in the file system (the infamous GOPATH
), with a specific naming scheme matching the git repository and other stuff like this. For 2018 it seemed we were going backwards. I'm sure there were perfectly good reasons for it to be like that, I just didn't care coming from languages that had solved (more or less) the issue of how to manage packages a long time ago. I ended up adapting to the go way but not happily.
Fortunately soon after that I discovered go dep
which allows the developer to have more control about what happens (but still inside GOPATH
). Dep works by having a file in which you list dependencies with their versions and revisions and by creating a lock file
(a concept many package managers share) while vendoring dependencies in a vendor
folder (usually ignored by .gitignore). This way, when you build the app (locally, on CI, on a server, or elsewhere) you can be sure about which versions of what packages the app is using.
The Go community decided to go one step further and create a preliminary version of what will likely be the official tool to handle packages: go mod
and modules. This new tool is out with Go 1.11.
The tool works this way:
- you write your app declaring which packages you need
- it creates a
lock file
and handles semantic versioning - it can optionally vendor files
What I love about it:
- it's dead simple and it's builtin
- it forces the developers to tag their libraries following semantic versioning. I hate having to go through master revisions to figure out what has changed because devs are too lazy to release their code. This will also probably encourage them to write changelogs for such tags
- it can clean up after itself (removing modules no longer used by the app)
- it tells you why you have this or that package installed
- it does not upgrade to a major version by itself (this is huge for large projects)
- it allows multiple versions of the same package in the same app (this is amazing! I can envision future scenarios of runtime hot code replacement a-la Erlang or Common Lisp, but maybe I'm over-reaching)
Additional details on modules can be found in Go's documentation about go mod and this is a nice overview.
Top comments (8)
Oh no, yet another usability problem of golang essentially solved.
Now what will stop its sinful hand?!
What do you mean with "sinful hand" ?
golang seduces projects, developers, and companies into investing into a golang codebase instead of going straight to Rust.
Sorry Mihail, I'm not sure I understand you. What do you mean? Can you be more explicit?
The existence of golang in the market at this point in history provides a halfmeasure between Java (or Node.js/Python), and going all the way to Rust.
Since go is a huge improvement, many people choose it for new projects, which further lowers the barrier to entry since the important libraries and integrations are already written. And we aren't just talking about small enterprise projects, but also crucial infrastructure such as
traefik
, openfaas watchdog, etc. It is now also supported as a runtime on major public cloud providers as a managed language.However, it is a half-measure in all regards, from development aspects such as type system and functional programming, to production aspects such as performance, memory usage, and binary size and cold boot time (important in faas usage)
Go's first public version is from November 2009, Rust's first public version is from July 2010. I guess they are from the same point of history
Anyway, I don't think Go and Rust entirely cover the same domains, as you hinted Rust is more of a systems programming language and Go is more of a general purpose language.
I'm sure expert developers can decide what to use in which context :)
Great article.
thanks!