Go And Renderman
The new staticly-typed language from Google called Go might displace C99 as my favorite compiled language. It’s so pretty, and so fast, that I’m even considering it in lieu of Python for common scripting tasks.
Minimalism is a core tenant of Go’s design, so it doesn’t take long to learn. It uses “channels” as a central concurrency primitive, which is a nifty way to write multithreaded code.
To try it out, I ported some of my old L-system code to Go, and created Go bindings for a subset of Pixar’s RenderMan interface. Here’s one of the first images I created:
In my demo, a description of a l-system consists of a maximum recursion depth, a list of rules, and a cache of transformation matrices. Here’s my first stab:
A few things to notice:
vmathpackage is my own (woefully incomplete) attempt at a vector math library in Go. It’s on github here, but I’m not sure where I’m going with it. We’ll see.
- Go’s type declaration ordering can be a jolt but don’t let it scare you. It feels like a reverse-polish calculator at first, but you’ll grow to love it. Rob Pike gave this a lot of thought; he discusses it here.
- Note that I define the
MatrixCachetype after its use in the
LSystemtype. Go lets you order things how you like, despite having a ridiculously efficient compiler.
- See how the types in the struct are all nicely aligned with whitespace? That’s not my doing; that’s taken care of by
gofmt, the code formatting tool that’s included in the Go distribution.
Parsing the XML description described in my previous posts (link) was a pleasure because the
encoders/xml package uses reflection to discover how to unmarshal the data. Go has a kind of metadata that you can add called tags, which are specified with strings in your field declarations. Here’s the same struct again, this time with tags:
Tags are just string literals and don’t need to be delimited with backticks. I used backticks here because I needed double quotes inside my string. Backticks tell the Go compiler not to honor backslash escapes.
Assuming a struct has been properly annotated with tags, you can unmarshal it like this:
Note that the official XML package is one of the areas undergoing churn. JSON is probably more appropriate for this kind of marshaling. Go gobs are interesting too, although not human readable.
Some of the same people who designed Go also designed UTF-8. When they that say Go identifiers must start with a “letter”, they really mean any character in the Unicode categories Lu, Ll, Lt, Lm, and Lo. This is especially nifty for us graphics developers, since we love Greek letters:
After discovering this feature in Go, I’ve become quite adept at using
M-x ucs-insert in my emacs editor.
Calling C functions from Go is relatively easy (going the other way around is a bit of a hassle). Go lets you embed the inclusion of C headers like this:
Since Go is a system-level language, mapping its types to C types is a fairly simple process. Here’s how I wrapped RenderMan’s
I suppose I didn’t need to use
defer here, but it seems like a good habit when working with explictly-allocated memory. The defer keyword is an interesting alternative to the RAII paradigm that grew out of languages with exception handling. Go doesn’t have exceptions, which I’m quite happy about. The language designers added features that do more than enough to compensate.
So far I’m loving Go. My only quibble is that the built-in math package currently assumes you want to use 64-bit floats, which isn’t ideal when interfacing with graphics API’s like OpenGL and RenderMan.