

Building Web Apps with Go - linhmtran168
http://codegangsta.gitbooks.io/building-web-apps-with-go/

======
shadowsun7
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.

~~~
nkozyra
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.

~~~
voidlogic
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:

[http://www.programcreek.com/2011/09/what-is-the-
difference-b...](http://www.programcreek.com/2011/09/what-is-the-difference-
between-a-java-library-and-a-framework/)

[http://tom.lokhorst.eu/2010/09/why-libraries-are-better-
than...](http://tom.lokhorst.eu/2010/09/why-libraries-are-better-than-
frameworks)

~~~
_ak
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.

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

[http://www.jeffreybolle.com/blog/run-google-go-web-apps-
behi...](http://www.jeffreybolle.com/blog/run-google-go-web-apps-behind-
apache)

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:

[https://www.digitalocean.com/community/tutorials/how-to-
add-...](https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-
ubuntu-14-04)

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 {
            panic(err)
        }

}

/* [http://stackoverflow.com/questions/14086063/serve-
homepage-a...](http://stackoverflow.com/questions/14086063/serve-homepage-and-
static-content-from-root) _/

func serveSingle(pattern string, filename string) {

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

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

------
codegangsta
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.

------
humanfromearth
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.

~~~
buro9
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](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...](https://github.com/russross/blackfriday#sanitize-untrusted-
content)

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.

~~~
e12e
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).

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

~~~
codegangsta
Great idea. Added an issue [https://github.com/codegangsta/web-development-in-
go/issues/...](https://github.com/codegangsta/web-development-in-go/issues/5)

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

~~~
dscrd
Well, they had an actual artist do it.

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

[https://golang.org/doc/faq#Whats_the_origin_of_the_mascot](https://golang.org/doc/faq#Whats_the_origin_of_the_mascot)

------
falcolas
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?

~~~
sethammons
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.

~~~
jpdlla
+1 for godep

------
rabble
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.

~~~
touristtam
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....

------
preillyme
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.

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

~~~
truncate
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.

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

