I added a new feature to my Go blog app that sort of automates a Tumblr-style "Ask Me" feature, which I found useful for other blogs I run on this codebase.
So Kirsle.net has gained an ask me anything page. It's like a Contact Me form except your question will become a blog post with my answer attached and you might receive a notification e-mail if you want.
In the past, I had been tasked to update some Python web apps to have them send e-mails out whenever they run into an uncaught Exception in one of our endpoints. This way we could identify any runtime errors in production and fix them.
In Python it was pretty easy: our web framework, Flask, provides a way to catch
any error that happens in any of your HTTP routes. Even if you didn't use Flask,
you can set
to a function and catch exceptions globally whenever other code failed to.
But then we had an app written in Go and it needed to have this feature, too. If it were simply a web service, this wouldn't have been bad, but this particular service listened on both an HTTP port and a separate TCP port in another goroutine.
Catching HTTP panics in middleware (or the standard
net/http library, which
catches panics itself) doesn't do anything to help catch the panics thrown by
the TCP server. So, like
sys.excepthook, I needed to find a way to globally
catch panics in my app.
This was surprisingly very hard to do.
Have you ever wanted to use Go to write shell scripts?
Where you could put a "shebang" line like
#!/usr/bin/env go, mark your source file executable, and run it?
I've found a pretty elegant way of making this possible, all in pure Go!
To write your own Go scripts, just include this shebang header (vim modeline optional). Your shell script does not need a
*.go extension. In fact you're better off not having a
///bin/true && exec /usr/bin/env script.go "$0" "$@" // vim:set ft=go:
And then put this file,
script.go, in your
$PATH and make it executable:
The Go codebase is a little rough around the edges and I'll be refactoring it over time. This is the first blog post on the new platform, so let me tell you about my open source Go blog!
The other day, I started a project to eventually replace the backend of Kirsle.net with a Go program instead of the current Python one (Rophako). It will support a similar feature set (being modular with even the core functionality, like user accounts and web blogs, being served by built-in "plugins" and allowing users to extend it with their own plugins).
The plugin system will support both compile-time plugins (your
main.go imports and registers all the plugins you need when compiling the binary), and run-time plugins using Go's plugins from *.so files support.
This post will focus on the former, compile-time plugins, and how I ran into a cyclic dependency issue and worked around it.
A very long time ago, I stumbled upon this article "Use Java for Everything". While I disagree that you should use Java for everything (or any programming language, for that matter), the author mentions that he wrote a wrapper script that lets him use Java for shell scripts (ones where you execute the Java source file directly, without the "write, compile, run" steps).
I wanted to do something similar for Go, because I had a very simple Go program I wanted to be able to throw into my .dotfiles repo and run without needing to do too many things first: a simple static HTTP server.
This is a cool tip I picked up from checking out other peoples' Go projects.
When you're new to Go, the documentation tells you about
$GOPATH which tells Go where to install packages and where the source codes to your project and its dependencies live. A lot of people might set
$GOPATH to be
$HOME/go, and work on their projects out of
This is something I wanted to rant about for a while: event loops in programming.
This post is specifically talking about programming languages that don't have their own built-in async model, and instead left it up to the community to create their own event loop modules instead. And how most of those modules don't get along well with the others.
Over the last couple months I've been slowly working on rewriting RiveScript in yet another programming language: Google's Go language! It's also my first project in Go, which is what tends to be the case (rewriting RiveScript in Java and Python were my first projects in those languages, too).
But this is the last time I'm going to be rewriting RiveScript from scratch.