Hacker News new | past | comments | ask | show | jobs | submit login
Building Web Apps with Go (gitbooks.io)
302 points by linhmtran168 on Oct 13, 2014 | hide | past | favorite | 40 comments

I tried to post this review on gitbooks.io, but couldn't. So I guess I'll put this up here:

This is a great introduction to building web apps in Go. (I started roughly two months ago, but had this book been around, I'd have been brought up to speed a lot faster).

Here's why: the predominant approach to building web apps in Go is to build on top of standard interfaces (e.g. net/http), and to keep things as simple as possible. Heavy, prescriptive frameworks are frowned upon. This is a great approach, but probably strange to people (like me) who come from prescriptive frameworks like Rails or Django.

Jeremy's guide sticks to Go conventions, while respectfully suggesting lightweight libraries that complement this approach. The guide is never "YOU MUST USE THIS", instead it always introduces the bare-bones approach first, and then tells you "hey, there's a 3rd party library that gives you some useful shortcuts on top of those." And indeed, each of the recommended libraries are idiomatic and easy to understand.

My review is probably biased, though, because I now have some idea now of how to write web apps in Go. But I certainly wished this book had existed when I first started.

I disagree that frameworks are frowned upon in Go, it's just that there aren't a ton that are worthy. People will usually be ok with Martini or Revel or Gorilla if they want something really barebones. None of those are really frowned up.

Where you may see people discouraging a framework is when you ask how to do something very basic and attempt to use a framework to solve it. In those cases, you lose the chance to learn exactly how the underlying processes work natively in Go, and since you're already writing in Go, you might as well do it from scratch. Plus all of your code is very reusable going forward.

But if you know how it works and want something quick and fuss-free for a full application nobody will steer you away from the better frameworks.

Many of the Go core contributors and well known to hold that frameworks present an unhealthy inversion of control compared to libraries. The standard library reflects this, for example as "net/http" is very much a library and works very different from applications using IIS or Apache. Many of the earliest gophers hold this position as well. I have been writing Go professionally since before Go 1.0 and I think saying "frameworks are NOT frowned upon in Go" is very much out of touch with the longest standing members of the Go community. I personally think there are cases for frameworks, but that they are few and far between.

Further reading for those interested:



In the case of net/http, I think it really turned out that simply integrating with http.Handler has so many more benefits than wrapping net/http with your own interfaces. Even Jeremy Saenz realized that and released Negroni after developing Martini.

I don't know that the parent meant all frameworks are frowned on, but more the "Heavy, prescriptive frameworks ... like Rails or Django."

I say if that's actually the case in the Go community, but I can understand getting that feeling starting out. I'm just starting with Go myself, and I had the same thought after some casual research digging through various blogs, tutorials and library suggestions.

As a newcomer to the language, it seems that there's a drive toward things being very explicit, using very little "magic", and composing smaller libraries, rather than using monolithic frameworks; all of that appeals to me.

If I'm way off base on that, I'd be happy to hear where my understanding is underdeveloped. Like I said, this is just what I get at first blush.

All in all, I'm really interested in checking out the book, and learning more about Go.

> it's just that there aren't a ton that are worthy.

It's just that writing a good web framework is actually way more complex than just a router.Martini,Revel or Gorilla are not webframeworks.

I believe Go is too rigid to allow something like Rails or Django. Go is for people who want C like performances with memory safety and easy concurrency. Go is not a "typesafe" python, at least it doesnt work like one until now. But I wouldnt be surprised someone comes up with a language built on top of Go that looks like a "typesafe" python or a Go++. That's what happens when people dont get their "nice things".

It's not like you need to ask a language community's permission to build your own thing in that language. Before Rails the Ruby community was very OO focused. Rails isn't very OO to be honest. It tends to used lots of composition and duck typing. You can see the major shift in the libraries before and after rails.

The question is, could somebody build a strong framework for web applications on Go? Maybe, i'm still learning the language myself so i don't know. Just because the language designers don't like it, doesn't mean that somebody won't come along and do it.

> always introduces the bare-bones approach first, and then tells you "hey, there's a 3rd party library that gives you some useful shortcuts on top of those."

We need something similar for Clojure web apps, since they both favor libraries over frameworks.

I haven't read it, but the developer of Luminus (a collection of libraries, not a framework) authored this fairly recently:

Web Development with Clojure: Build Bulletproof Web Apps with Less Code (https://pragprog.com/book/dswdcloj/web-development-with-cloj...)

Luminus: http://www.luminusweb.net

Edit: argh italics

This seems to be the approach most new languages use. People in the Clojure community also emphasize using libraries over frameworks. I think the reason is is that earlier adopters tend to prefer this approach and there is a lot of agreement and development work required to make a full fledged framework like django.

I feel you on this, also coming from Django background, there is no equivalent yet for golang, though I've been skimming with revel for some time, it's still incomplete from what I want. This is just perfect opportunity to learn something that is more disconnected, but syncs with harmony. :)

Thanks for the feedback guys! The book is still a work in progress. It started as curriculum for the workshop I gave a couple days ago at DotGo. The plan is to continue making it awesome and to make the examples more complete.

I run a simple Go server behind Apache for my weekend project (http://www.thespanishsite.com). I started with this blog:


I also use MySql on Digital Ocean with a $10/month droplet. The few issues at first where that I started with a $5/month which didn't enough RAM so I'd run out of memory until I created swap:


Still need to make it a daemon, but I'm not finished. I have one big method to set up my pages. I could write a blog, github repo or create a summary page on my site, if there's any interest.

func runWeb() {

    serveSingle("/robots.txt", "./robots.txt")

    http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./css/"))))
    http.Handle("/resources/", http.StripPrefix("/resources/", http.FileServer(http.Dir("./resources/"))))
	http.Handle("/static",  http.FileServer(http.Dir("./static/")))

    http.HandleFunc("/chinese", chineseHomeHandler)
    http.HandleFunc("/french", frenchHomeHandler)

    http.HandleFunc("/chinese/numbers", chineseNumbersHomeHandler)

    // Many handlers deleted ...

    http.HandleFunc("/", homeHandler)

    // http.ListenAndServe("localhost:9999", nil)
    port := GetPort()
    fmt.Println("listening...", port)

    err := http.ListenAndServe(port, nil)
    if err != nil {

/* http://stackoverflow.com/questions/14086063/serve-homepage-a... /

func serveSingle(pattern string, filename string) {

    http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, filename)

Check out supervisor (http://supervisord.org/). Super painless daemons if you're like me and hate writing init scripts.

UPDATE: I can longer edit my original comment.

I realize that a bunch of unformatted code on HN is not that useful so I created a quick starter Go Webserver on github: https://github.com/melling/GoWebServer

There are a couple of scripts to build and run the server.

What was causing you to run out of RAM? I've been running a Django app w/ Postgres on a $5 droplet for months without memory issues, despite Django/Gunicorn being sort of a memory hog.

Aren't there a lot of required packages to build a webapp? I would recommend against using any of those at least in the beginning. Maybe gorilla/mux, but even that can be avoided.

Don't just add deps you will never use, it's going to make your life painful.

For the example given, you probably don't need Negroni, Controller or Render.

Mux is also possibly surplus, but does tidy up the extraction of values from routes a little. But to be totally honest the given example isn't complex enough to start letting Mux shine (multiple values on URLs, a single app serving both http and https).

Blackfriday (for Markdown) is necessary if you want to convert your text input into HTML, though there is a missing dependency here which is Bluemonday.

Bluemonday ( https://github.com/microcosm-cc/bluemonday ) is a HTML sanitizer and ensures that XSS supplied via the Markdown box is stripped before rendering - I wrote that, it's based on the whitelisting approach as demonstrated by the OWASP Java HTML Sanitizer. Blackfriday even recommends you clean your untrusted inputs: https://github.com/russross/blackfriday#sanitize-untrusted-c...

SQLite3 is required, or at least some SQL provider is going to be required if the tutorial wants to fully demonstrate actually saving content and using one of the established interfaces (database/sql) to do so.

So you could reduce this to three deps: Blackfriday, Bluemonday, SQLite3 and stick to core/stdlib http for the actual "web app in Go" stuff.

The other deps, it is debatable whether or not they are essential, certainly the larger web apps will find that they are simplified and easier to read and work with by using some combination of Mux, Negroni and Controller depending on your needs. Render I have not used and do not have a strong opinion on.

Thank you so much for this comment about xss. It can be very hard to keep track of how new tools and frameworks handle (or not) xss, sql injection, sessions, ssl pinning, secure cookies etc -- all essential for making usable web apps. Especially with "small simple examples" where the writing is good and the code seems reasonable - it can be hard to believe that the author is showing off dangerously broken code (rather than say, having input run through a whitelist hidden behind a library, and simply not calling attention to it).

Without your comment the book would've done me more harm than good - now that I'm aware of the blanks, I can learn with the awareness that I'll have to assume similar errors lurk in the other sections (or: if it looks a little too simple, it's probably because corners were cut, going from simple to simplistic).

In Go its pretty difficult to build an application with unused dependencies - the compiler complains

So you end up with a lot of these: _

Which is okay, they act as a todo list of sorts. Search your program for _ when you feel like cleaning up. And you can handle all those errors you've been swallowing while you're at it.

Use `goimports` as a save hook in your editor. It analyzes your code and inserts/removes import lines as needed.

Other than the occasional need to fix up an ambiguous import that it guessed incorrectly, I haven't touched import lines in my code in a year.

You should never write Go code by swallowing errors first and promising yourself you'll clean it up later. You should be coding the error path first, and backfilling your business logic. The error path directly informs your method definitions and the structure of your code, which resist modification once they're in-place.

It would be helpful for Go newbies if a 3rd column (description) was added to the table in the "Required Packages" section.

If there's one thing Go did right, it's the logo/mascot. (sorry for OT)

I still prefer Plan9's.

Reminds me of a popular 4chan/reddit draw, you just need to add the 'tail'.

I keep giggling every time I see it, because it reminds of Pedobear[1]

1. http://en.wikipedia.org/wiki/Pedobear

Well, they had an actual artist do it.

The same actual artist that did the Go mascot also did Plan9's.


The hard-coded dependencies on GitHub (not to mention they're dependencies to code owned by someone else) have always bothered me. It seems like it would create a real problem for compiling, auditing, or even just testing code in the long run; and this example relies on a ton of them.

I haven't kept up with the state of the art Go packaging; have these problems been addressed?

Vendoring is the approach taken by many. Personally, I use godep. It vendors into your source the different libraries that you are using at a specific version (git hash in all the cases I use). This handles the compiling and locks in the particular version of the library which you have presumably audited. As far as testing goes, as long as you are making use of interfaces, testing should be easy enough.

+1 for godep

I don't mean to be a bit difficult here, but i wonder if the tutorial's author had anybody actually try it. I mean it seems like there's tons of missed steps, sections missing, assumed bits which aren't done. Each example i try tends to have other things done, uh, as exercises for the reader, which are required before the code samples even work.

mmm my feeling as well. Trying out on a Windows 7 machine (sic) at the moment and heroku is complaining about MySql. Might have been an idea to deal with the deployment later during the tutorial....

Is using gorilla/context really the only easy way to store an retrieve data that is specific to the current HTTP request? Seems like there should be a better way to map values and retrieve them later from a global mutex on a map of request objects, or something.

Is this guide specific for Go on Heroku or its concepts can be easily applied elsewhere?

Its just deployment which can be a bit different and its a small part of everything. Libraries are same, whether you deploy on Heroku or AWS.

This looks awesome! Thanks a lot, Jeremy for doing this and sharing it with us!

Applications are open for YC Winter 2022

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact