Posted on December 17, 2013 by

Which Go Web Framework?

I’ve been around the block a couple times. I’ve built production services on soon-to-be dead open source projects more than once. I’ve been burned by hype and excitement in new technologies. It sucks. So if you are building a Go web app, which web framework should you pick?

Right now Go is super hot, and developers are all writing their own web frameworks in order to learn the language. Most of these will still be around in a year, but they aren’t going to be actively maintained. So I’m not giving a list or silly comparisons or benchmarks or any of that ridiculousness. Just some advice based on my remarkable history of failure.

  1. Choose the framework that you understand
  2. Choose best practices over cleverness
  3. Choose Age over beauty
  4. Ignore the active contributor count
  5. Ignore benchmarks

Choose The Framework You Understand

This is the most important advice. Even if your framework has a corporate backer and is popular, it may die or become orphaned. It’s a little early in Go web dev to have any one framework entrenched in the community so much that it will move on leaderless. But if you understand your framework then you can still maintain it into the future (provided you have the source).

I’ve maintained dead PHP frameworks and Python frameworks in production deployments. It can be a pain to have to build new functionality into a framework, but you can do it.

What I can’t possibly do is maintain database code. When the “NoSQL” movement got started, I chose a document database that seemed cool and just fizzled. I have no business trying to fix bugs and maintain that kind of a project so I had to migrate. I should have stuck with a working relational system until there was a clear choice in the NoSQL world.

Understand the code you are using. You may be annoyed in the future, but not in huge trouble.

Choose Best Practices Over Cleverness

As projects get larger, they come up with their own ways of doing things. This locks you into a framework and makes it difficult to add new functionality. If your framework dies, the value of an open source community disappears. You have to customize packages to fit your dead framework. So your framework better be pretty close to compatible.

This is our first actionable tip. Make sure your framework accepts Go standard library packages, and isn’t doing something custom. Let’s take a look at a standard Go http handler function:

type HandlerFunc func(ResponseWriter, *Request)

If you are looking at a framework, you should make sure that your handlers can accept these two parameters. This does two things:

  1. Makes sure you will always be able to have direct access to the request and writer
  2. Let’s you know that any other packages expecting these arguments will work in the future.

Let’s look at some real world applications. Martini injects data into your handlers based on the arguments they specify. So you can require the HandlerFunc arguments to be passed, and Martini will give them to you.

Tiger Tonic also implements the HandlerFunc interface. However a very common use of Go is serving up JSON APIs. If you look at the Tiger Tonic Marshaler, you need to pass a specific signature which does not match the HandlerFunc interface. So you may run into additional coding challenges when implementing third party code.

As you look at all the available frameworks, you’ll notice that using the Gorilla Web Toolkit packages is pretty standard. Are you planning on adding Websockets to your app at any point in the future? Check out the GWT Websocket package. Notice that in order to upgrade a connection to a Websocket, you need to have access to the raw Request and ResponseWriter.

Choose Age Over Beauty

This may be more of a fascination with this silly expression, but I think it applies. Just like illness, software bugs only present themselves when a lot of people have been touching something. That shiny new framework is only shiny and new because nobody has used it yet. Go is new in general, so just beware. A lot of code may not have seen the horror of a production environment and the users it attracts.

I chose web.go to build a prototype application last year. It was a nice framework. I needed a lot of basic features that it didn’t have yet. I also had pretty severe time constraints so I had to maintain my own fork with my changes. As things progress, my implementations differ from those introduced into the main fork and now I’m using my own web framework or having to rewrite a lot of code.

It is always nice to have hard problems solved when you arrive. With a language as new as Go, this may not always be the case however.

Ignore the Active Contributor Count

Unless the project has already lost that new car smell, active contributors can fade pretty quick. Revel has a very healthy commit history. However looking at any specific time period you may have very few commits, or a ton of commits across several people. There is no data (that I know of, other than manual inspection anyway) to determine if these commits are features or bug fixes. Are they removing extraneous features? Or commented out code?

As the contributor count drops, you may be looking at a project with no more bugs! Or another new shiny framework may have popped up and everybody left for the new toy.

I just find this to be a hard metric to use to really quantify a projects future success.

Ignore Benchmarks

If you have a counter example to this, then you should use the benchmarks in that counter example. But most often benchmarks are for “Hello World” cases which are best handled by a web server written in assembly.

If you are going to have users login and pull data, then you will probably be writing your own benchmarks to test sessions and database access and cache misses. You aren’t going to find any generic benchmark to help you out.

One pretty neat idea entering into the Go world is using a Trie for route parsing. I first saw this in ant0ine’s go-urlrouter package. Tiger Tonic uses it as well. This is a neat benchmark because it shows a significant speed improvement in the route lookup (over regular expressions). But remember, almost everything else out there (in any language) uses regular expressions to parse routes. While this is neat, you may be optimizing the wrong part of your program.

Posted on December 8, 2013 by

Prepping for the New Year

I’m going a completely new direction this time. Typically I come up with habits and life hacks and other ridiculousness that I want to start or stop or change. Then I plan to begin all of those things in January.

Then I write a blog post the following December talking about how I’ll do it all for real this time.

But no more! Why wait for the new year when you can start today? So thats the idea. More writing. More effective communication. More community involvement. More tangible accomplishments. So where to being?

Learn something new and present it, comprehensibly, to a group of people every 3 months.

This would cover community involvement, communication, and a bit of writing. So really it covers everything. I think there is a lot to be gained from presenting to a group.

More reading.

I’d like to start reading again. I really don’t enjoy reading very much though. I’ll find authors that I enjoy, and then read all their stuff. But they are really few and far between. The rest of what I read, I tend to rush through and not retain at all. Which makes it a waste of time really.

Less procrastination

That’s why I’m starting now, instead of the new year. I think that waiting is just silly. Why delay?

Posted on November 26, 2013 by

The Fear

During what was supposed to be a routine lunch, I was passed the resume of an incredible individual. I didn’t care about the insane GPA from MIT. Being smarter than me is pretty common. But this guy is simply a better person than I am. That’s when I felt the fear.

This person is looking for a job?

Why am I seeing this resume? Shouldn’t this be given to NASA or SpaceX or something?

When it gets down to business, I’m a web developer. Sure, I have other hobbies that I get to from time to time. But I’m not who you go to looking for advanced algorithm optimization. Or to roll out a paradigm shift in some new realm of Computer Science. I am who you need when you have to identify, record, and fix a program if it crashes. This guy should be trying to find out if a program will halt.

Are there not enough advanced jobs out there? Will I have to compete with this kind of resume in the near future? I’m getting older man, I don’t know if I can keep up with this stuff. This guy was traveling around the world, raising money for charities. He had an impressive career history as well. Lots of large scale projects.

If anything keeps the fire burning, its the never ending stream of other people who are always better than you. I really don’t know how I’m still allowed have a job developing software. But I’m so far down this path its really the only thing possible for me.

I’m sure that guy will find a job quick. I certainly hope I don’t run up against him in a contract bid though.

Posted on November 22, 2013 by

It’s All Going to Fail

So just get used to it. The Internet, I mean. If you use it frequently, you probably already realize it breaks kind of a lot. But if you don’t use the internet a lot, like all the people who use my software, you think that the Internet always works. So when something bad happens, it is because the website is broken. It could not possibly be poor connectivity or user error.

When I have user problems, I get reports like

“The website doesn’t work”

“I tried uploading when I signed up, but it didn’t work”

“My account doesn’t work”

All of these are totally useless. But those are the reports I get. So, really, it’s up to me to make a better application that users don’t have problems with. Then I won’t get these error reports.

Your Javascript Isn’t Going to Load

I have a rock solid web app design. I minify my javascript and CSS. I deploy my assets to S3 to reduce requests to my server. I use CloudFront as a CDN to make sure my users have great download speeds no matter where they are. What could possibly go wrong? Well, for starters, sometimes the CDN just doesn’t load my Javascript. Not very often at all mind you. But if I have even a moderate amount of requests coming through the app, then every couple of days a page load will fail.

If my site isn’t built right (and when is it ever), then parts of the webpage just don’t work. Sometimes things fail silently. Sometimes the page doesn’t load correctly. While most people would refresh the page, my users say “The site stopped working, so I canceled”.

RequireJS, YepNopeJS, and HeadJS are all tools to help deal with this. I’ve been using HeadJS recently because I don’t have to rewrite much code, like you do with RequireJS.

<head>
<script type="text/javascript">
/* minified headjs code */
</script>
<script type="text/javascript">
    var scriptLocations = [
        '',
        'cdn3.domain.com/js/app.min.js',
        'cdn2.domain.com/js/app.min.js',
        'cdn1.domain.com/js/app.min.js'
    ];
    var loadtries = scriptLocations.length;
 
    function loadapp(callback) {
        head.load(scriptLocations[loadtries--], callback);
    }
 
    function testReady() {
        if (loadtries == 0 ) {
            document.location.reload();  // Fail… what to do if we continually fail
        } else {
            if (loadFailed()) {
                loadapp(testReady);
            } else {
                docready();   // This should call whatever would normally be run first
            }
        }
    }
    head.ready('mainScriptLabel', function() {
        testReady();
   });
</script> </head>

That’s the code I use to attempt multiple loads. There is a commit pending to allow promises. That would be a lot better than this. But for now, this has solved the odd CDN load error.

You Will Have Phantom Errors

I noticed that once I get over a few hundred users on a web application, they start having errors that I can’t ever reproduce. But the errors do actually exist. I’ve recently started using BugSnag to track these errors. I use Bugsnag because they had the easiest setup that worked with my existing codebase. I was able to start receiving live javascript failures in minutes.

Now that I am tracking these odd problems, I have to deal with my minified JS code, which is CDN loaded. So whenever a problem happens in a script loaded from the CDN, CORS breaks, and I get a useless Script Error Line 0 message. I’m actually still getting this working in all browsers. Setting up CORS through AWS gets some users, but certainly not everyone.

You Will Use Ugly Hacks

Is it just me, or does Heroku’s CloudAMQP Tough Tiger fail all the time? It’s to expensive for all this failure. See, I have problems connecting and uploading to S3 fairly regularly. So I put upload jobs in a queue and return a 202 to my users. However, queueing the job in CloudAMQP routinely fails with a pika.exceptions.AMQPConnectionError: 1. I could just tell the user to try again, but the entire point of this post is that users don’t try again. They say “The website is broken” and give up. So I have to create silly loops to increase the likelyhood of the job being queued in CloudAMQP.

    i = 0
    queued = False
    while queued is False:
        try:
            connection = pika.BlockingConnection(params)
            channel = connection.channel()
            channel.queue_declare(queue=CLOUDAMQP_QUEUE, durable=True)
            channel.basic_publish(
                exchange='',
                routing_key=CLOUDAMQP_QUEUE,
                body=message_body
            )
            queued = True
        except Exception as e:
            logger.error(unicode(e))
            i += 1
            if i == 3:
                queued = True

I find this rather ugly. But it seriously reduced upload failures. So it remains.

I’m out of fuel for this rant. I wanted to remind myself that everything that can go wrong, will go wrong. The people reporting that something has gone wrong won’t be helpful. You have to plan for all this upfront and move back your deadlines if need be.

Posted on October 18, 2013 by

Golang October Meetup

After a long hiatus, GolangDC and GolangNOVA let their powers combine to put on a spectacular show at UberOffices in Rosslyn. We hit the 50% no-show right on the mark (as much as you legally can with an odd number of RSVPs). So the meeting was a statistical success.

Wes Freeman (@wefreema) covered web services and testing tools and introduced us all to the Mexican Pizza from zPizza. During his talk we walked down some pretty great tangents; ISO8601 pains, an AI game called “Ants” where several contestants were using Go, and probably a third that I don’t recall.

Ants sticks out because the game happened in 2011. Go didn’t have a stable API yet and upgrades could be bad. An unholy alliance between the Go developers formed, where they forced the game designers to put a freeze on the Go version because updates kept breaking everyone’s code.

There are several ideas in the works for the next meetup. As usual, we are going to try to make this a more frequent event. So see you next time!

Newer Posts
Older Posts