End Grain Cutting Board

I made an end-grain cutting board, and it’s about the coolest thing. It’s 1 ¾” thick and made from white maple. I’ll take you through the steps I followed.

I’ve been a metal guy for years now. I love welding, I love machining, but recently I discovered that glued wood joints can be far stronger than I ever thought. We kinda needed a second cutting board, so I watched a few videos and read a few guides and decided I could probably build one. Last Wednesday I sketched out some plans, and worked out that I needed two pieces of 8/4” wood measuring at least 7 ½” by 24”, ideally walnut or maple or cherry.

I went to Owl Hardwood on Wednesday night and picked up a really nice piece of 8/4” maple, measuring about 49” by 10”. That piece was about $60 out the door (nice hardwood is surprisingly expensive!). I took it by the South Side Hackerspace on Friday, cleaned up the edges, and cut them into two inch strips, and got them glued together.

Of note, the table saw sled I used was not perfectly square. I wound up having to flip some of the strips around so that the resulting workpiece was more or less square. I’ll probably have to build a new table saw sled one of these days.

Wary of the out-of-square sled, I cleaned up the edges on the sliding compound miter saw. I was able to work quickly and keep burning to a minimum.

I made a jig out of a precision scrap of pine 2x6, and set that at 2”.

Then I cut my workpiece crossgrain into 2” strips…

and I set the strips on their sides, like so.

The strips had a little bit of tearout on the sides that was preventing them from joining up nicely with one another, so I put the smallest chamfer on the corners with a Stanley #27 block plane.

When all was said and done, it looked like this:

I arranged the pieces in the clamps and flipped every other piece around to get a nice checkerboard pattern.

I reused the precision pine jig to make a custom pine glue spreader, like so:

Then I applied glue…

and gave it the squeeze.

After letting it sit about an hour, the glue was hard enough to work with. I squared up the miter sled on the table saw and cleaned up the edges.

I then planed the workpiece down. The planer was really disliking cutting the end grain like that, so I wound up having to go super slow, turning the height adjustment no more than 1/8th turn at a time (probably taking off somewhere between 1/64” and 1/32” at a time). The planer really beat the trailing edge to heck, so I cleaned that up on the table saw as well.

I put a ¼” roundover on the corners with a router, then started sanding. Two problems exposed themselves here: First, I really should have bought new sandpaper (maybe starting with 80 grit, then moving up to 200 and finally 400 grit) rather than just using the 200 grit that I found. The planer’s blade needs replacing, and it left some deep scratches in the surface that sanding was able to minimize, but you can still see them. Second, sanding on the table saw like that caused me to pick up some of the 3 in 1 oil I used to oil the table. Whoops!

Finally the workpiece was sanded and ready to take home.

I bought a couple bottles of butcher block oil (just food grade mineral oil) and a thing of butcher block wax (just food grade mineral oil and bee’s wax) from the Home Depot. At this point my friend Erin will be yelling “No you idiot it’s so much cheaper to buy that oil in bulk! I told you I had some!” But it was late, and I was impatient, so I was willing to spend a few extra bucks to get it done.

Once home, I soaked both sides in oil. I poured a bunch on, spread it around with a paper towel, and waited 15 minutes. I did this three times per side with the oil, then once per side with the wax. The oil brought out the wood’s pattern, and it looks amazing.

My wife helped me pick which side was the bottom, and I installed some anti-skid rubber feet. I might replace the screws with stainless hardware down the road, but this will work for now. Deciding to install feet on one side is a trade-off; I could leave both sides open and make the cutting board reversible, but having feet on the bottom makes it slip around less and also lets air flow on the underside to help it dry off. As an aside, installing the feet was my first chance to use my new Makita drill and driver, so I was excited!

I flipped it back over and let it sit overnight. The oil oxidizes and forms a semi-hard sealing layer. I re-coated the board the next morning, and again later the next day. I got to use it last night to chop some star fruit, and I can’t tell you how exciting it is to have made something this beautiful and functional with my hands.

Golang Philly Talk

I gave a talk at Golang Philly last night! Here are some slides.

Top Ten Home Thorium Core Reactor Tips

This is the first in what I hope may be a series of retrofuturistic pieces styled after 1950s era Popular Mechanics DIY home improvement articles. I hope it’s fun to read!

More and more homeowners nowadays find themselves switching away from antiquated electricity sources like geothermal and municipal grid, and adopting a super-efficient Home Thorium Core Reactor instead. Known for their safety and low waste, these reactors will power a home for pennies a day. However, ask Thorium Core Reactor early adopters, and you’ll hear many stories about their fickle nature.

The editorial team here at Popular Robotics has compiled a list of tips to keep your Home Thorium Core Reactor working like new. We hope you’ll find them useful.

1) Use High Quality Thorium

It may be tempting to purchase your thorium at the local home improvement superstore, but impurities in your fuel will lead to nasty buildup on the primary heat exchanger coil. Your radioelectric efficiency (W/Sv, or watts per sievert) will drop, and you’ll have to power down your reactor more frequently for maintenance. It’s well worth the few extra dollars to find an independent isotope fuel distributor and purchase Grade 5 (that’s 99.5% pure) or better thorium.

That said, if you have a bag of cheap thorium that you want to use, grind it finely and mix it 10 parts to 1 part charcoal ash and 2 parts deionized water. Let that sit overnight, then use a minimum of 10 parts DI water to rinse away the ash. The remaining thorium will be at least Grade 3.

2) Clean Your Coils

Even using high quality fuel, you’ll want to keep your Home Thorium Core Reactor running at peak efficiency, right? The easiest way to do this is to power your unit down at least twice a year to clean buildup from your primary and secondary heat exchanger coils. Scouring with a paste made from baking soda will take care of most of it, but excess sulfur scaling may need to be dissolved away using a weak lye solution. Your coils don’t need a bright finish, but they should appear clean and free of debris before going back in the reactor.

We like to plan our maintenance right around the Spring and Fall Equinoxes. You’ll be without power for a few hours, so it’s important to pick a nice time of year so your home doesn’t get too hot or too cold.

3) Capacity Planning

Your Home Thorium Core Reactor may be rated at 24kW peak, but it will wear a lot more slowly running continuously at 25% max power than at 75%. If you’re planning to convert to Home Thorium Core Reactor power, or if you’re planning to replace an aging first generation unit, it may be better to size up rather than choosing the smallest unit that fits your needs.

Larger Home Thorium Core Reactors don’t just last longer — they’re more efficient too! Your bigger heat exchangers will collect buildup much more slowly, and beefier dingle arms will withstand more output changes.

4) Keep Your Output Steady

It may be tempting to buy a flash Home Thorium Core Reactor that can respond to demand spikes in seconds, but rapid output cycling goes hand in hand with rapid thermal cycling, which, of course, leads to premature manifold cracking. Replacing a damaged manifold can take a few days, during which your family will have to go without power or purchase expensive municipal power.

Instead, you may find it more economical to purchase a capacitor bank and place it in line with your power output. The bank will handle any sudden surges in demand, allowing your reactor to sedately adjust output.

5) Check Your Dingle Arms

The dingle arms move the control rods that moderate your Home Thorium Core Reactor’s power output. Like all moving parts, they wear. A seized dingle arm can prevent your reactor from powering up, or, worse, prevent it from powering down. In the second case, you run the risk of a thermal runaway, and your reactor would SCRAM itself. That’s a costly repair that can take several weeks, during which time you’ll be left with little choice but to buy expensive municipal power.

When you take your reactor down for maintenance, inspect each dingle arm. Make sure they move freely, and check the bearing surfaces for excessive pitting or scoring.

6) Keep Spare Dingle Arm Bushings On Hand

If you find a worn dingle arm and you don’t have spare bushings on hand, you’ve got a few choices:

  • Bring the reactor back on line, order a spare, and then take the reactor back off line when it comes in
  • Keep your reactor off line until the spare comes in
  • Bring your reactor back on line, order a spare, and hope nothing goes wrong until the next scheduled reactor maintenance

None of these are very pleasant. If you had a handful of spare bushings sitting in your tool box, this would not be a concern.

7) Use Rubber Bushings

Fast output adjusting Home Thorium Core Reactors use expensive polyurethane bushings because they’re firm and afford for very fast dingle arm adjustment. They also transmit a lot of harsh vibrations back into the control module. Some Home Thorium Core Reactors have oversized stepper motors to account for this, but yours might not.

If you’ve followed our advice by overplanning for capacity and installing a capacitor bank, you don’t need fast output adjustment. Use the rubber bushings. They’re cheaper, they last longer, and they’ll cause a lot less wear on your control module.

8) Keep Your Cool

Your Home Thorium Core Reactor works on the basic principle of moving energy from a hot area to a cool area. If the temperature around your unit gets too high, your radioelectric efficiency will drop. We’ve seen drops as great as 50W/Sv in a 12kW unit mounted in direct sunlight in the middle of a South Florida summer.

The obvious place for a Home Thorium Core Reactor is in the basement, but basements just aren’t common in some parts of the country. If that’s not an option for you, we recommend the north side of your house (for those of you in the northern hemisphere, of course). That will keep your reactor in the shade during the heat of the summer day, and you’ll see the returns in the form of less thorium fuel spent.

9) Get Up To Code

You’ll want to make sure your home wiring is up to code when you install your Home Thorium Core Reactor. In most municipalities, you should have pulled a permit and had your installation inspected before the first power up, but we understand that doesn’t always happen. Weak aluminum to copper connections can act like resistive loads, wasting power and consuming excess fuel, causing your reactor to run much harder than it would otherwise. Make sure your breaker box and breakers are up to at least the 2145 standard, because your home reactor is capable of delivering more power than the municipal grid, and you need the protection and heat dissipation offered by modern breakers.

10) To Insulate or not To Insulate

Surprisingly, given the low cost of Home Thorium Core Reactor generated power, it may not be worth upgrading your home insulation! For the average home, unless you’re adding more than 20 R value points to the roof and walls, it’s cheaper to simply heat and cool the space as necessary when amortized across the 20 year operational life that can be expected from a well-maintained reactor before it needs its first major overhaul. Additionally, if you live somewhere with very cold winters, we’ve seen kits that pass water or glycol around your secondary heat exchanger windings and can be used to run a radiator system or pre-warm your forced air heating. You can expect to see around 2W/Sv efficiency decrease running a system like that in the winter, but you wind up spending less fuel overall heating your home.


Over the past decade, Home Thorium Core Reactor technology has proved itself an economical and reliable alternative to municipal power sources, and we expect to see adoption increase in the future. Whether you’re on the fence about installing your first reactor, planning your next upgrade, or simply enjoying economical, clean energy, you can follow these simple steps to get years of reliable power generation.

Jeep Box

One of the problems with Jeep Wrangler ownership is there’s nowhere to store things out of sight. Your backpack, laptop, whatever, it’s all hangin’ out there in the open. Even when you’ve zipped the top up, there’s nothing between your valuables and a set of sticky fingers besides a thin sheet of clear vinyl.

I wanted to feel better about leaving things in the Jeep, and I wanted to design something sturdy so that I could still carry heavy things in the back of the Jeep. I also wanted to cut down on the general clutter in my cargo area, and I wanted to practice welding.

I imagined something like this:

So I started with some rough measurements.

That’s a top view and rear view of the back of the Jeep. I had 34.5” between the brackets where the rear seat would have mounted if I had one, 35” of length to work with, and 15.5” between the bottom of the opening and the bottom of the rear window.

So, to summarize, what I wanted was a drawer and a frame to hold that drawer that fit in the above-defined envelope. The frame would have to be reasonably sturdy, because I’d like to put things on top of it too. I’m the kind of person who thinks really well in design tools, so I fired up Autodesk and got to work.

This was the first pass, and some measurements. I ran it by some Internet folks, and they suggested diagonal bracing.

My plan was to attach a sheet of plywood to the top using T-nuts and cap screws, and to put roller bearings on the horizontal bars running along the sides to act as drawer slides. The T-nuts and cap screws were entirely reasonably priced through McMaster-Carr, but the roller bearings were about $5 ea. I found equivalent skate bearings on Amazon for about $1 ea.

Using the CAD drawings, I figured out what pieces I’d need.

I did some math, and figured I could fit that into 19 pieces of 37” x ½” square stock (N.B. I was wrong, and probably should have ordered 20 or 21 pieces). From Metals Supermarket, that was just over $50.

I got to welding.

Then I realized, I’d have to mount this in the Jeep! I’d figured I’d use the rear seat belt mounting bolt, but I forgot to locate that with my previous measurements. I rectified that.

I bought a sheet of flat steel stock, milled in a hole for the seat belt bolt, and welded that into place. A test-fit revealed that I’d milled the hole in the wrong place, so I had to fix that, first with the angle grinder, then with a plasma cutter.

Finally, it went to paint! I wanted to powder coat it, but I got a $150 quote for powder coating. A little rich for my blood. I used a can and a half of Rustoleum black enamel instead.

While that was curing, I designed the wooden top and drawer.

I decided to make it all out of ½” plywood, cut from ½ sheets of plywood (because half sheets are easier to move than full sheets). The drawer, I figured I’d just use brads and glue to hold it together. If it fell apart, I could always re-do it.

Because the wooden pieces were just rectangles, I let the robots take care of cutting them out.

The next night, I loaded up all the pieces and started attaching them together.

The skate bearings I bought had an inner diameter that was just a little bigger than the screws I used, so I turned the screws into cones on the lathe to locate the bearings better (not pictured, but I wish I had).

Everything in the Jeep so far:

It’s been about a month since I finished all that, and I have the drawer together and installed; I just haven’t taken pictures of it yet. It served us well on our trip to Georgia — our valuables went into the drawer, and my wife’s big suitcase got strapped to the top.

How I Clean My Boots

I own a pair of Redwing leather boots. I really like these boots. They’re formal enough to be worn with dress clothes, but sturdy enough that I can grub around fixing cars and installing drywall. Good boots take care, especially to keep them waterproof and looking clean. This is what I’ve been doing.

I start with some dirty boots. Look at that dirt!

We gotta get rid of all that dirt. I use an old microfiber towel. I normally wipe the dirt off every few days, but for a deep clean I’ll remove the laces and really go at it.

It looks okay, but you can see the dust stuck in some of the natural wrinkles of the leather, as well as the boot’s seams. To get that, I go at it with a stiff plastic brush.

I brush against the grain, sometimes stretching the boots to get into the wrinkles. I also brush inside all the seams, and around the base of the upper.

I follow up with Saddle Soap and a toothbrush. I put a sliver of saddle soap into an old coffee mug that’s ¼ full of hot water, stir that up well, and go to town. I get all the seams, re-touch all the wrinkles, and really scrub wherever I’ve scuffed the leather. The saddle soap contains glycerin (so I’m told) that helps to protect the leather. I scrub one shoe, then the other, then I rub them both dry with the same microfiber towel.

Dried on the left, still wet on the right. We’re already doing pretty well, but we could do better.

I pre-heat the oven to 170 degrees (the lowest it will go), remove the top rack, and put aluminum foil on the bottom rack. I stick the shoes in the oven for 20 minutes or so. This dries the shoes out, gets them nice and warm, and opens up the pores in the leather. Then I rub the shoes with mink oil.

The mink oil makes the leather more supple, it hides scratches and scuffs, and it adds water resistance. I smear it on heavily, especially the scuffed areas on the toes. Those areas seem to drink up mink oil, so I add more and more until they stop.

The shoes go back in the oven for another few minutes to let the mink oil really soak in, then I pull them out and turn the oven off. I take a clean rag (or old tee shirt, or old sock) and buff the shoes to a medium luster.

Shoe polish? I don’t use it on these shoes. I like the look of the natural leather, and I’m going to keep caring for these boots in this way as they wear in.

Assigning Globals in Go

This has bitten me in the butt a few times this week, so I figured I’d blog about it.

Be careful with your scope when you’re assigning values to global variables in Go!

Here’s a quick little example. We have a globally scoped variable, foo. In our main(), we call makeSomething(), which returns to us, we hope, a something and a nil error. Then we make that global foo variable point to that variable.

package main

var foo int

func anInt()(int, error){
  return 7, nil

func main(){
  foo, err := anInt()
  if err != nil {
      print ("Oh god!")
  println("foo was assigned the value of", foo)

func printFoo(){
  println("I see foo as", foo)

Easy peasy, right? Nope.

$ go run stuff.go
foo was assigned the value of 7
I see foo as 0

What we’ve done is created a locally scoped variable foo that disappears once we exit main()! That’s because := is a short-form variable declaration and assignment. The compiler believes we are declaring a variable foo and assigning it the value returned by anInt().

Let’s run through a few possible variations:

foo alreay exists

func main(){
        foo := 3
        foo, err := anInt()          // Weirdly, no error here
        if err != nil {                  // Local foo is delcared,
                print ("Oh god!")      // assigned 3, then assigned 7.
        println("foo was assigned the value of ", foo)

Just assign

func main(){
        foo, err = anInt()           // Compiler error!
        if err != nil {              // undefined: err
                print ("Oh god!")
        println("foo was assigned the value of", foo)

Use a temporary variable

Of course, if we do this:

func main(){
        f, err := anInt()
        if err != nil {
                print ("Oh god!")
  foo = f
        println("foo was assigned the value of", foo)

we see:

$ go run stuff.go
foo was assigned the value of  7
I see foo as 7

…which is what we’d expect. However, that’s a little fugly. Let’s tidy that up a bit.

Pre-declare your error

func main(){
        var err error
        foo, err = anInt()
        if err != nil {
                print ("Oh god!")
        println("foo was assigned the value of ", foo)

Declare an error called err, do the assignment, and then go on with your day.

Anyway, lesson learned. When you’re dealing with globally scoped variables and multiple return values and something doesn’t behave the way you think it should, make sure you’re using the variable you think you’re using.

Introducing Uluru

I don’t work for Backstop any more (but you should), but back when I did, we discovered we had no idea how long it took our users to load our tools. Hell, we couldn’t even figure out how many clicks per month we had! I was working with New Relic trying to get a quote from them, and the best I could do was 2 million plus or minus 800 thousand. We had insight into how long it took our servers to respond to requests, but no thought was given to DNS, loading outside resources, rendering DOM, etc.

We tried New Relic Browser, but that failed for two reasons. First, something in the few-hundred-kilobytes of minified JavaScript was conflicting with something in our JavaScript in a way that broke automated testing. Second, on a sales call, we determined that Browser really wasn’t going to tell us the information we wanted to know. It’s a good tool, for sure, but it didn’t expose the depth of data we wanted.

Colin found a tool called Yahoo Boomerang which seemed to do what we needed. It would collect metrics on how long it took the page, and various resources on the page, to load, and it would report those data back to a server over here. Simple, right?

I took two issues with Boomerang. First, it again broke our testing. Second, it used some ridiculous scheme of a GET request with URL parameters inside of an invisible iframe to get data back to the server without any cross-site request issues. This seemed entirely too complicated, and simplicity was one of my overarching goals. I decided to roll my own.

I was sitting in the audience at Monitorama, and one of the speakers mentioned logging how long clients spent loading pages. I asked him about it, and he mentioned something in Vanilla JavaScript that allowed for that. I did some research, found out about window.performance.Timing, and thus Uluru was born.

The name, incidentally, came from back when I was experimenting with Boomerang. I needed a server to throw Boomerang data at, so I picked the famous Australian sandstone formation Uluru.

Design goals

There exist other solutions, commercial and open source, for recording and reporting on browser telemetry. It was found, however, that these solutions were significantly complex, and in many cases interfered with JavaScript we were already using, causing JavaScript errors and preventing the browser from rendering UI elements. Therefore, the design goals of Uluru became:

  • Minimalism: Uluru.js is 47 lines of whitespace-heavy JavaScript. It should be extremely readable.
  • Light weight: When minified, Uluru.js squishes down under 500 bytes.
  • Speed: Uluru.js has no dependencies on other JS libraries.
  • No hacks: Uluru.js makes a single POST request to a remote server. It does not e.g. cram metrics into query parameters and make a series of requests GETting hidden images or iframes.


Client side

Uluru is a function that, when called, gets the time since navigation started and some other metrics, and sends those to an endpoint. We’ve set it up such that uluru(endpoint) is called when window.onload fires, under the assumption that most of our product is useful by that point.

Uluru collects the following data:

  • url: the window.location.href
  • connectionTime: the time (ms since UNIX epoch) the connection was initiated.
  • connectionDelta: the time spent establishing a connection to the server
  • firstByte: the time spent waiting for the server to respond with the first byte of data
  • responseDelta: the time the server spent sending a response to the client
  • loadTime: time between the navigationStart and window.onload events.

It also calls window.performance.getEntries() to provide specific timing on every resource (script, image, stylesheet, etc.) included in the page load.

Server side

Uluru rolls all the data it collects up into one PUT request. The easiest way to collect Uluru data is to include a data collection REST endpoint in your existent web application (or, if you’re feeling clever, make your web proxy route Uluru requests to a specific Uluru logging server.

Alternatively, you could set the Access-Control-Allow-Origin header to allow the browser to make POST requests to a separate server you’ve spun up for this purpose.

Either way, what we’ve wound up doing is writing the Uluru data out to Splunk, and aggregating it there in interesting ways.


Here’s some of the data we were able to collect!

Page loads and Appdexes

Photo & Video Sharing by SmugMug

One neat thing we didn’t have before is an easy way to count how many page loads our system saw, how many unique users we had actively using our system, or how many clients were logged in on a given day. When you start making changes to system performance, you start thinking about things differently when you consider the 1ms wait you just removed will be multiplied by 73,000 over the course of a day.

Appdex is an interesting measure of system speed. You select a goal speed (2 seconds on the left, 4 seconds on the right), and you count page loads. Every page load that took under the goal speed counts for 1. Every load that took greater than the goal speed but under twice the goal speed counts for .5, and the rest count for 0. You divide the counted page loads by the total page loads, and you get a number between 0 and 1 that gives you a decent metric for how happy or sad your users are.

One really interesting thing we saw from this, we found by looking at individual clients. One of our clients had a significantly lower Appdex than the rest. We did some digging, and found that a condition in their data made every JSP load a huge number of records from the database to generate a list they never used. We disabled that for them, and they got much happier without ever realizing they were sad!

Speed breakdown

Photo & Video Sharing by SmugMug

This is a bit more boring, but it lets us know how many page loads are fast, acceptable, slow, or super slow. Comparing, e.g., last hour with last 7 days lets us see any system wide problems before our clients call in.

Page load histograms

Photo & Video Sharing by SmugMug

These let us know at a glance how our page loads are distributed. We could, for example, notice a bi-modal distribution. It wouldn’t affect our average or median scores, but it would be indicative of something fishy.

I once noticed a particular user sending back negative page load speeds. I investigated it for a little bit and decided it was just one of those weird things that happen when you rely on multiple sources of time.

Slow pages

Photo & Video Sharing by SmugMug

This report gives us some neat insight into what’s been taking a long time to load. You look at each one, make sure it makes sense, and then use this graph to help prioritize your projects.

Time sinks

Photo & Video Sharing by SmugMug

Likewise, just counting the total amount of time sunk into a resource is helpful. You might (much like we do) have a page that clients hit all the time. It might load in under two seconds, but if you can shave 10 % off of that, you’re saving 20 hours per week aggregated across all of your users.

You can get a lot of really interesting data from visualizations like this. Use these to help justify speed projects.

Further directions

Currently, the Uluru project includes some stub code for a generic REST endpoint. I want to flush this out into something that writes logs for splunkd or logstash, or forwards data to services like Sensu or Riemann.

Internet Jukebox

One of the hackerspaces at which I am a member installed a Beaglebone Black on their door and put a speaker outside.

Now we can play sounds to the street, but to do so, you have to ssh into the Beaglebone. That’s not bad, but it’s a hassle. Okay, so can I make a REST endpoint that plays music?

(The answer is yes.)

Here’s the repo. Let’s go through it.


There are two endpoints, / and /play/. / returns a simple HTML form that lets the user upload a sound file. When the user clicks Submit, a POST request is made to /play/. The sound file is extracted from the form data, and asynchronously processed.

The sound file process is thus: it is saved to a temporary file on disk, mplayer is called on that file, and then when that process terminates, the sound file is removed.

Serving a static html page

is easy.

controlfs := http.FileServer(http.Dir("control"))
http.Handle("/", controlfs)

There’s a directory called control, and it contains index.html. When you hit /, you get index.html. Wildly easy.

Creating that REST endpoint

http.HandleFunc("/play/", func(w http.ResponseWriter, req *http.Request) {
    if req.Method == "POST" {

        if req.ContentLength > 10485760 {
            w.Write([]byte("File size capped at 10mb"))

        soundFile, headers, err := req.FormFile("soundFile")
        if err != nil {
            log.Printf("Error getting soundFile from Form. \n %s", err.Error())
        log.Printf("Recieved %s", headers.Filename)
        w.Write([]byte("All done!"))
        go playASound(soundFile)

    } else {

        //TODO(cagocs): maybe return 200 with the name of the sound playing?

Briefly, here’s what we’re doing:

  • Setting up a url pattern, /play/.
  • Defining an anonymous function that runs when you hit /play/
  • Checking the request method.
    • if it’s POST
      • Check the content-length. If it’s greater than 10 MiB, return a status code 400.
      • Get the soundFile out of the form.
      • Log the filename
      • Return a status code 200
      • Asynchronously play the file
    • if it isn’t
      • Return a status code 405
      • I considered returning a string representation of all the files playing, but didn’t.

One quick point: Yes, it’s possible to spoof the content-length in a request. I didn’t check for that. If you decide to run this in any sort of mission critical sense, maybe watch out for that.

Playing a sound

func playASound(file multipart.File) {

    soundFile, err0 := ioutil.TempFile("", "sound_")
    if err0 != nil {
        log.Printf("Error initializing new file")

    buffer, err1 := ioutil.ReadAll(file)
    if err1 != nil {
        log.Printf("Error reading mime multipart file")

    err2 := ioutil.WriteFile(soundFile.Name(), buffer, os.ModeTemporary)
    if err2 != nil {
        log.Printf("Error writing file to disk")

    cmd := exec.Command("mplayer", soundFile.Name())

    err3 := cmd.Run()
    if err3 != nil {
        log.Printf("Error playing file %s", soundFile.Name())

    err4 := os.Remove(soundFile.Name())
    if err4 != nil {
        log.Println("Error deleting %s", soundFile.Name())


So now we have a sound file in memory. How do we get it to the speakers? I spent a long time screwing around trying to figure out a “pure Go” solution, gave up, and decided to cheat. The Beaglebone Black will probably ship with MPlayer; why not use that?

I skimmed through some code examples and came up with the solution above. playASound is running asynchronously, so it can spend some time doing what it needs to do. It creates a new TempFile, and writes the sound file there. It then creates a Command that calls mplayer and passes the name of the temporary file to mplayer as an argument. Mplayer plays the file, and when the mplayer process completes, our goroutine closes and removes the temporary file.


I decided to not take my own advice and open this up to the general internet a few days ago. I used port forwarding on my router to forward :3030 on my external IP address to port :3030 on my laptop, and ran the program. I posted about it on IRC, forums, and made an Imgur post, and I got a few people participating.

I found it to be incredibly stable. No crashing, no issues running 4 to 6 instances of mplayer on top of one another. I was pleased with how the server handled unexpected EOFs and connection timeouts. Lastly, I discovered that letting people assault my ears with a barrage of mp3s is fun!

Sun Visor Bracket

I shattered the sun visor bracket on my Jeep in the cold this winter, so I did the only sensible thing. I tried to machine a new one.

I started with a block of 2” by 4” aluminum stock. I cut 2” off of it with a band saw. The blade popped off of its guide with about 1/10” left to go, so fixing that was a fun diversion.

I finally got a piece mounted in the Bridgeport and milled a few reference surfaces. I sent this picture to my friend to ask about the finish on that side milling. He said it was normal, if a little fugly.

Photo & Video Sharing by SmugMug

I call this picture, “Where the hell did I put my calipers?”

This is one of my favorite parts of machining. On the left, you can see the rough cut that’s out-of-square. On the right, the machined surface.

I took a bunch more cuts, and got here.

Then I messed up.

Notice the middle part? That would be perfect, if the sun visor stuck up. Of course, it hangs down, so this part is completely worthless. Fortunately, I have enough stock to make a second one.

Message Queues and Go

I gave a talk last night to the ChicaGoLang meetup entitled “Message Queues and Go.” It went over using a Message Queue Broker as a backbone to tie together a service oriented archetecture, with examples in Go.

I put my slides here:


and you can follow along with the video here:

The examples in the code will, unfortunately, not work because they rely on RabbitMQ running on a specific IP address / port.

Let me know if there’s anything I got wrong or missed!