Golang Ramblings from a Python Dev

I’ve been spending time lately learning Go and I thought I’d throw some of my thoughts down here. As the title implies my experience is mostly in Python so expect lots of apples to oranges comparisons!

Taken from the golang blog

Tooling

I guess the first thing that jumps out is the quality of the tooling, I’ve only had a chance to play around with a few of the CLI’s features but already I’m impressed with how simple it makes some day to day things.

When you’re looking at new code for the first time the first thing on your mind is usually vendoring dependencies (I didn’t realise ‘vendor’ is a verb, ya learn something new every day). “go get …” will download and install individual dependencies but it can also recursively scan through a project to save you the effort:

go get -d ./...

This can pull in code automagically from git repositories (mercurial, bazaar and subversion too) which is nice and it doesn’t involve installing an extra package like pip/setuptools.

When you’re adding changes to code don’t forget about gofmt. It takes advantage of the relative ease of parsing Go’s syntax to automate/enforce certain elements of coding style like use of whitespace. It’s also really easy to include in your workflow; I use fatih/vim-go, a vim plugin that (among other cool things) runs gofmt every time you save changes. If vim’s not your style (pun not intended) then it’s easy to find docs for setting up a git hook that runs gofmt before you commit.

There are some other tools that use Go’s simplicity to automate away the boring stuff. These are tools I haven’t had a lot of time to try out but for the adventurous: godoc “extracts and generates documentation for Go programs” and gofix which “finds Go programs that use old APIs and rewrites them to use newer ones.” The later one sounds particularly ambitious! Reminds me of 2to3, which never offered any guarantees other than a helping hand; you were still expected to go most of the porting work yourself.

Next step is usually building/installing code; the “go build” and “go install” commands serve all your needs here. No need to choose between packaging libs like setuptools and distribute! The problem here is that what these packaging libs provide for is a standard way of declaring package metadata so that they can be found on an index like PYPI, which leads me to…

Argh! Packaging!

So far this is the first big thing missing for Go and I’m not entirely sure how I feel about it!

On the one hand there is no need to set up and actively maintain your project listings on a centralised site; all you need to do is to choose (and choice is important to developers) which site you host your code on.

On the other hand PYPI can really leverage that metadata and offer a powerful way to search for the package you need. If you haven’t tried browsing by package category before, give it a quick try so you can see what I mean. I can wait…

I tried looking into a similar resource for golang and most of the internet pointed me to godashboard.appspot.com/project, which seems to be down at the time of writing. After a little bit of research it seems that the listings it hosted were moved around some wikis till they found their new home at https://github.com/golang/go/wiki/Projects. Having this page in the language’s git wiki seems to makes sense in terms of go’s philosophy but it just leaves me wanting something better.

But I Digress… Lets Talk About Testing

So the compiler hasn’t found any problems in the code; it all builds without issue. Hurray!

The next thing to check is tests and the command for running them is (big surprise here, drum-roll please) “go test“. This quite frankly makes “python -m unittest discover” look like an afterthought.

Here’s something that shocked me when I was writing tests: there’s no assertions in Go! The aim here was to remove a crutch that developers too often use to avoid thinking about proper error handling. That should be a top consideration when you’re writing server-side code; if you’re not careful with errors requests will die and cause lots of trouble for the client.

So what do tests look like in a world without assertions? Not that different really, assertions are just if statements with some syntactic sugar to make things look a bit more formal. All you need is to write your own if statements and make calls to “t.Fatal(…)” if things look broken.

I did some soul searching regarding this; is there anything that we really lose from leaving assertions out of the language? At first I was a bit miffed because I’m used to the array of assertions available as member functions of unittest.TestCase in Python but I got over it quickly! Keystrokes saved while writing tests aren’t worth it if it means people get lazy with error handling.

Convention Over Configuration

The common theme that I keep coming back to in my head here is “what can we automate by relying on a convention and what should we let developers control by way of configuration?”.

Go’s tooling stuff all depends on a strict directory structure and syntax (which probably required a lot of thinking on Google’s part). Python’s package distribution relies on the maintainer filling out setup.py. Both languages also have conventions regarding writing test cases to facilitate test discovery.

It makes me think a lot about the upfront investment in terms of reading docs. When you’re starting out learning programming, documentation can be daunting; there’s a hell of a lot of it! I’m not ready to say which language has the greater learning curve for developers starting out but it’s a very important consideration

More Rambling?

I realise that this post has been far from a comprehensive comparison and that there are many important things I left out, e.g., goroutines vs asyncio, support for paradigms like OO and functional programming, third party libraries, etc.

There’s way too much to cover in a single blog post. I hope to write more as I get familiar with the language and maybe I’ll ramble about other technologies too!

If you have any comments, suggestions, or questions feel free to get in contact with me! I’d love to hear from you.

Advertisements
Golang Ramblings from a Python Dev

I’m back!

I know that it’s been a while since I wrote a post! I haven’t been keeping up with my own goal to write something new at least every week.

At first this was because I was on holidays and internet access was spotty at best. More recently I’ve been very busy at work and not had as much time for reflection. I wanted to call this out here to keep myself honest and to make a fresh commitment!

Taking the time to write this blog is in my own interest because it pushes me to develop certain aspects of myself (writing skills, communication, confidence). I love that it gives me an excuse to explore technical subjects in greater depth and to showcase what I find out. Lastly (and I know I’ve said this before) I hope that it serves as a record and guide for others who are starting out in the software space.

I would urge anyone with an interest in tech to start a blog of their own. It’s a great way to become a more rounded person and, with enough time and effort, will have a massive effect on your career! Reach out to me on twitter if you need some advice about this.

I’ll be back with some more weekly updates soon!

I’m back!

Weekly Notes – 26/7/15

Setup.py and rpm.spec:

https://rkuska.fedorapeople.org/pyp2rpm.png

So recently at work I needed to package a tool we wrote at work. The tool was written in Python (big surprise) and it was designed to be run as a daemon so it had an init-script.

Most Python tools are packaged by writing a `setup.py` script. There are actually a number of tools you can use (I’ve used distutils and setuptools in the past) and there’s a bit of a confusing history regarding which tool is recommended. I mostly use setuptools.

Most (all?) of the software we use in work are packaged as RPMs which are built from a `rpm.spec`. I don’t want to get bogged down in the advantages/disadvantages of this approach here so I’ll keep this part short: It’s more powerful than setup.py scripts but not as well documented. It’s simple enough to install files to specific places that setuptools/distutils don’t make easy (like an init.d script) or to execute code during build/install. On the other hand you really need to understand the ins and outs of your application when writing an rpm.spec. There are some subtle things that happen when you’re building RPMs and that can cause a lot of confusion when you’re starting out.

Now, you can use setuptools to create an RPM package, which is handy. It bypasses the weirdness of rpm.specs and setuptools nicely wraps up some of the messy details of where you should install packages so that they’re available on the python path. Unfortunately, this approach limits you to the features available in setuptools and you lose out on all of rpm.specs flexibility! Just not good enough for my needs.

What I really wanted to do is write both and mix them together. An rpm.spec that delegates some of the hard work to setup.py and looks after the detailed work itself. Luckily this is possible!

Here’s what you need inside your rpm.spec to get setup.py to do the heavy lifting.

The build phase is pretty self explanitory:

%build
python2.7 setup.py build

Then during install you need to point it to install inside the RPM build directory and to save a list of files to INSTALLED_FILES:

%install
python2.7 setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES

Then that file list can be passed into the `%files` directive by using `-f`. This means that you won’t need to maintain a list of files that setup.py will be looking after.

%files -f INSTALLED_FILES

You can still list any other files that are taken care of by the rpm.spec after the `%files` directive.

If you try this out yourself, you can check that it all worked by listing the files inside the resulting rpm:

rpm -qpl path/to.rpm
Weekly Notes – 26/7/15

Hello world!

Why I started this blog

I’m not very good at writing about my experiences, I prefer to just talk. In fact I could ramble on about my own thing all night, constantly meandering and exploring tangents as I go.

I’ve decided that I should put more of an effort into collecting my thoughts in blog form so that I can focus them. At the very least I hope this will make me a better developer but maybe I’ll help others who run into the same stumbling blocks on their own journey.

What I intend to write about

To start off I’m hoping to write a weekly summary of interesting things I learned; whether it’s something from my professional work or a pet project.

In the future, I may post updates about some of my pet projects or events I attend but no promises just yet.

Hello world!