Wandering Thoughts archives

2013-04-15

Go's friction points for me (and a comparison to Python)

A commentator on my entry on Python's data structures problem asked in part:

So, what's next, if anything? I take it Go wasn't a revolution in the way the migration from C to Python was. [...]

This brings up the complex issue of my views on Go. Part of the issue is that Go has a bunch of friction points right now. Some of them are intrinsic in the language and some of them are simply artifacts of the current situation and will hopefully change.

(I wrote more about where I think Go fits into my programming back in GoInterest.)

In general I don't think that Go will ever be as fast to program in as Python is (in the sense of how long it takes me to write a program, not in how fast it runs). Go goes to a lot of work to reduce the amount of bureaucracy involved through various features, but Python is simply at a higher level in terms of eliminating make-work and as a result it's significantly more flexible and adaptable. The tradeoffs involved are sensible for both languages and their goals; as discussed Go has a strong emphasis on large scale software engineering and Python doesn't.

(To put it one way, Go is a great language for large scale software projects but I almost never write those. As a sysadmin I'm generally a small scale programmer.)

I'm going to split this into current and intrinsic friction points, then do this in point form to keep the size of this entry from exploding. First, the current friction points:

  • Go is not pervasively available in the way that things like Python, Perl, and awk are. This is especially true of current versions of the native Go toolchain, which is really what you want to be working with. This is merely a pain for personal development (I can always build the toolchain myself) but a relative killer for work programming in our environment.

    (To put it one way, 'first you download and build the compiler' does not make Go sound attractive to my co-workers.)

  • Go's standard library is limited and portions of it are crazy. This can be (somewhat) fixed with external packages but then I have to find them and evaluate them and so on, which is a hassle. It would be less of a hassle if people started making OS packages for various good add on Go packages, the way many Perl and Python add-on modules are only an apt-get or yum command away on most Linuxes.

    (Part of why this matters to me is that $GOPATH makes me grind my teeth. It strikes me as such a bad fit for working with multiple projects under version control that it's painful.)

  • The state of web frameworks for Go seems unclear right now. I especially care about form handling and validation, especially for database-backed forms (because this aspect is generally the largest pain in the rear to code by hand; it's what drove me to Django for my Python web app).

  • Debugging is less friendly with Go than with Python, because if you screw up in Python it will dump out a great big verbose stack backtrace; often this points me to exactly the mistake I made. Go is a lot terser and thus less helpful.

(There are also pragmatic issues with using Go in production.)

I thought that I had several intrinsic language issues but at this point all I can think of is the general extra annoyance of explicit error handling as opposed to Python's tacit exceptions. I understand why Go makes the choice it does but Python's exception-based approach is just plain convenient for quick coding and it means that you can write much less code (you can aggregate error checks and even skip writing explicit ones and your program will still abort on errors).

(I consider things like Go type assertions to be part of the general price paid for static typing. I can't really describe static typing as a friction point, although to be honest it sort of is.)

Also, as I've written before I maintain that Go's obsessive focus on goroutines with basically no support for select() et al is ultimately a mistake. Goroutines cannot do everything and there are real situations that they don't cope with (not unless you allow them to be canceled from outside while they are in nominally blocking routines).

(If I use Go more I may find some additional irritations. Python is a relatively featureful language as compared to Go, so I may find myself missing things like function decorators at some point.)

GoFrictionPoints written at 02:32:36; Add Comment

2013-04-03

How to make sysadmins unhappy with your project's downloads

I tweeted:

Dear every project that doesn't have an URL for their tarballs that is easily wget'able: ha ha. Very funny. Please stop. #sysadmin

Let me expand on this a bit. First, I'll give a pass to everyone who has access-restricted downloads; there is no good way to make them easily fetched. This is for everyone else, all of the various projects that have public downloads.

Here is the thing: sysadmins are not necessarily browsing your website on the machine where they actually want the source code. In fact it's almost certain that they aren't, since very few sysadmins run Firefox or Chrome on their servers. What sysadmins want to do is use 'Copy Link Location' on the (nominal) URL of your project's distribution tarball, open a connection to the server, type 'wget <pasted URL>' on it, and wind up with a sensibly named tarball (or zip file or whatever) of your source afterwards.

There are at least two ways that this goes wrong. Sadly I am going to have to pick on the Django web framework for the first one, because it inspired my tweet. The download URL for Django 1.5.1 is:

https://www.djangoproject.com/download/1.5.1/tarball/

If you feed this URL to wget, you do not get something called 'Django-1.5.1.tar.gz' but instead a file called 'index.html' (which is the gzip'd tarball that you want, just with the wrong name). This is because wget operates in a very straightforward way; it puts whatever it fetches in a file named after the last component (or index.html if the last component looked like a directory, as it did here). Wget does have an option to change this, --content-disposition, but I had to look it up in the manpage. Sysadmins do not appreciate being forced to look up (and then type) long options to wget to get your tarballs.

The fix for this is straightforward: your download URL should have a last component that is the name of the distribution tarball or applicable file. Then wget will do the right thing.

(Github does a variant of this. The stated URLs of a zipfile of a repo are things like <user>/<project>/archive/master.zip, but the fetched file is supposed to be called <project>-master.zip. Browsers that pay attention to the HTTP Content-Disposition header will save it under that file name; wget will at least use master.zip.)

The other really bad thing you can do is what Sourceforge at least used to do. The nominal 'download' links on Sourceforge projects didn't go directly to the files (despite appearing as if they did); instead they went to an interstitial HTML page that told you about mirrors and and automatically started a download (I assume through the use of a HTML '<meta http-equiv="refresh" ...>' in the page). This is of course completely impossible to feed to wget, which doesn't interpret this HTML <meta> tag at all. You should not do this sort of trickery; your download links should actually be links to the files, not to any sort of interstitial experience. If you need to make people go through a mirror, do that with an HTTP redirect and put an explanation about it on your download page.

WgetableDownloads written at 00:28:48; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.