Maybe it’s just me, but as a Python/Django dev I really enjoy having PyPI as a canonical source for packages. Everything else in the article read positively, but I feel like examining 5-6 libraries (especially when I’m starting out and don’t know what idiomatic Go looks like) is unnecessary overhead.
I’ve been programming in Python for years, and if there is one thing I don’t miss, this is PyPI and pip and setuptools and all this stuff.
With a centralized repository, you tend to think that the package with the most obvious name (for example mysql for a MySQL driver) is the best one. This is usually not true.
In Go, you can search for a package at godoc.org or go-search.org. You can also check the number of stars/downloads/commits in GitHub as an indication of popularity and activity.
In Go, when you need a dependency, you directly fetch the source code from git/hg/svn/bzr. You directly work on the source. There is no “package”. There is no intermediate concept or tool to master. That simplifies things a lot in my experience.
The JVM ecosystem is where I’ve seen packages really work. Everything is a jar. Everything is on maven central. Everything has a unique, canonical name. If you want to e.g. proxy external dependencies so that you can build if they go down, you’ve got a single point to insert that intermediary rather than worrying about git/hg/svn/bzr. You get checksumming for free, you get stable, reproducible builds, but upgrading is easy because you don’t have your own copy of the source. “diamond” dependencies (your app depends on B and C, each of which depends on A) resolve sensibly. “inverted” dependencies (e.g. for a “plugin” to a library) work the way you would expect and want.
I wouldn’t want to work without some concept of a “release”, some distinction between hacking away on a library vs. a version that’s suitable for external people to use. So in the Go approach you end up using tags or git hashes or so on; packages achieve the same thing in a simple, consistent way.
In the Go world:
I’m not necessarily arguing in favor of Go’s approach. I’m just saying that you really haven’t made a compelling case for packaging.
For me, I happily live in both worlds. pip for Python (well, pure Python) packages works just fine for me. So does the go tool.
The Go approach has its upsides. There’s a lot it doesn’t do for you, and most people see this as a negative. I guess that’s OK. I choose to see it as a positive. It removes another tool which can often be a source of frustration. If you have to, say, vendor your dependencies yourself (or rely on some external source like gopkg.in), then upgrading is simple, stable and reproducible. Always.
How about when some of your dependencies have transitional dependencies for different versions of the same library in the classpath?
Assuming my dependencies used dependency ranges, maven will figure out the best version to use for this “grandparent” library, and error out the build if there’s no overlap between the ranges.
Fully isolating dependencies would allow that use case to work, but would break the “plugin” use case, which IMO comes up more often (it’s interesting that npm has an explicit bodge for this case). And I suspect I’d find it very confusing to work with two different versions of a library when debugging.
Yup. Having things have a canonical name, e.g: org.example.lib.mysql and com.oracle.lib.mysql over just mysql, allows for less confusion.
Everything in Go has a canonical name too. They look like this:
There’s no confusion.
What happens when a project moves from github to bitbucket?
Its name would change - just like it would change from com.github.ziutek.mymysql to com.bitbucket.ziutek.mymysqlng if you were using Java.
Also note Ziutek could:
What happens when I want repeatable builds and the project decided to change the URI and had a little bit of fun with the tags in their repository?
Rubygems I can easily mirror, this, I cannot.
You can: vendor the dependency.
“Aw crap, what did those chucklefucks do to my github.com/foo/bar? It’s called quux on bitbucket now? And they renamed my tags?! And all before I vendored my dependencies!”
go get bitbucket.com/baz/quux
git checkout tags/used-to-be-v1-hahaha-now-try-to-figure-this-out
gofmt -w -r '"github.com/foo/bar" -> "bitbucket.com/baz/quux"` *.go
It’s not necessarily the best, but it’s not as painful as you might think.
Repeatable build implies that I don’t edit my past source for that.
Vendoring is an option, but then I don’t need to refer by URL in the first place.
just like it would change from com.github.ziutek.mymysql to com.bitbucket.ziutek.mymysqlng if you were using Java.
But in Java it usually wouldn’t. You have that level of indirection, so you can host your project in a new place but keep the existing groupId and avoid making trouble for your users.
change the canonical name to ziutek.com/mymysql.git and self-host a git repo.
change the canonical name to ziutek.com/mymysql and put a special meta tag on that web page for Go
Cool, particularly the meta option (now if only there were a place that offered easy hosting of those…), but these only really work if the developer does them right at the start of the project, when they’re least experienced and least worried about these kinds of issues.
I agree that that works very well when you’re a mature developer, but I think that the concept of a package is a decent abstraction to have. It’s the reason I was okay with using Ubuntu as my daily driver (almost everything is just a sudo aptitude install away). I think I understand Python well enough that I could get by if I needed to pull source directly, but it’s a daunting task for some newcomers.
sudo aptitude install
everything is just a sudo aptitude install away
You can just use go get. For example, to get a PostgreSQL driver, you use go get github.com/lib/pq.
go get github.com/lib/pq
What does the concept package brings you that you miss here?
Apologies, I may be out of my depth; I haven’t used Go for anything more than a couple of toy scripts to check out syntax. It just seems to me that the concept of having a singular repository for dependencies is a comforting thought.
No apologies needed :)
Almost all Go libraries are on GitHub, BitBucket, Google Code or Launchpad. Usually, a quick search on these sites, filtered by language, gives you what you need. I expect also meta-search engines like go-search.org to improve and maybe give you the benefits of a central repository without the drawbacks.
There is also gopkg.in, which has some interesting properties.
Versioning and the assurance that libraries can’t just “disappear”.
Yes, Go provides workarounds for that, but it requires additional work from the developer and can easily be forgotten (plus, it’s a hack, not a principled solution).