

Web.go – Web applications with Go - Walkman
http://webgo.io/

======
JesseObrien
This doesn't look like it expands much on what the Go web server does and it
also looks like it's been abandoned. Last commit was ~5 months ago from today,
with most of the rest being 7-8 months ago and 40-something issues piled up.
For some better web experiences in Go I'd check out revel[1] or gorilla[2]

1\. [http://robfig.github.io/revel/](http://robfig.github.io/revel/)

2\. [http://www.gorillatoolkit.org/](http://www.gorillatoolkit.org/)

~~~
elithrar
web.go is definitely pretty old/semi-abandoned.

I wouldn't recommend Revel to many (it's Play heritage isn't well suited to
Go, IMO) but the Gorilla toolkit—a collection of useful packages that extend
net/http, rather than a full-blown framework—is _exceptional_. mux/pat, schema
and sessions are all such useful tools and I've been working with them for a
couple of months [in my spare time] as I build a web app w/ Go as a non-
programmer.

Some other solid Go web packages/tools:

• beego ([https://github.com/astaxie/beego](https://github.com/astaxie/beego))
- a well-maintained, active project if you want to head down the framework
route. Closer to Sinatra/Flask than Django/Rails.

• "Bones"
([https://github.com/peterskeide/bones](https://github.com/peterskeide/bones))
- a useful template for an application/some good design patterns

• nosurf
([https://github.com/justinas/nosurf](https://github.com/justinas/nosurf)) -
CSRF middleware that plugs into net/http (and therefore works with gorilla/mux
or pat)

• gorilla/context
([http://github.com/gorilla/context](http://github.com/gorilla/context)) -
request context. Great for passing per-request variables (i.e. CSRF tokens,
saved forms, etc) between your middleware and your wrapped handlers. Set up
some Get and Set wrappers around your specific keys so you can avoid writing
out type assertions every time you want to retrieve the stored object.

• go.stripe
([https://github.com/drone/go.stripe](https://github.com/drone/go.stripe)) - a
fairly complete Stripe library.

• blackfriday
([https://github.com/russross/blackfriday](https://github.com/russross/blackfriday))
- Markdown processor.

Obviously, frameworks (and ecosystems...) like Flask, Sinatra, Django and
Rails have an advantage in that you can get stuff done today: they do a lot
for you. And, for many use-cases, performance will never be a problem.

Saying that, writing HTTP logic in Go has been surprisingly easy, and the
small amount of extra boilerplate you have to write (if you're sans-framework
like me) is nice when you realise how darned fast your application is. Being
able to deploy a single binary and front-end it with nginx also reduces a ton
of complexity.

PS: Once I finish this thing off over the Christmas break, I'm hoping to write
up a few articles on the bits-and-pieces that took a bit of time to "get
right". Also have a minimalist (i.e. wraps HandleFunc, not Handler) CSRF
package in the works.

~~~
skrebbel
> _Being able to deploy a single binary and front-end it with nginx also
> reduces a ton of complexity._

Just wondering, how is that different for other compiled languages, like
Java/Scala (Play) or C#? You copy all jars over, optionally put an nginx in
front, and off you go. And is it really that different for Ruby or Python with
virtualenv? What's the added complexity there, in terms of deployment?

Note, I don't really mean to be critical or something, rather I wonder whether
there's some advantage of Go that I've not understood.

~~~
elithrar
> What's the added complexity there, in terms of deployment?

You need to install the interpreter/runtime (and sync versions/use rbenv/etc)
+ you need to install your libraries + ensure that they are kept up to date
(i.e. virtualenv or bundle install).

A lot of this is shortcut these days thanks to rbenv, virtualenv, etc, but
it's still not automatic.

I can import a ton of libraries into my Go project on OS X, cross-compile a
binary (`$ GOOS=linux go build`) and upload it. If I update the packages on my
dev machine, it doesn't matter. Recompile, upload, restart. This goes for many
languages that compile native binaries, but Go does make it really easy.

~~~
deckiedan
Don't you also have a load of static content (js, css, etc), templates, and
configuration files to upload / sync as well?

But yes, it does sound a bit easier.

~~~
Octplane
With some clever compilation stuff, you can also pack most static assets
directly in your application (see [https://github.com/jteeuwen/go-
bindata](https://github.com/jteeuwen/go-bindata) ). This gets even more
magic...

------
marketer
Wow, I didn't expect this to make the top of Hacker News :)

Web.go is a wrapper on top of Go's net/http standard library. The authors of
Go aren't from a web programming background, and the net/http server
interfaces was a bit more clunky than I'd like, which is the main reason
web.go exists. It's not really designed to be a full-fledged web framework.

I used it to build a few apps. There's an old article about one of them here
(although the app has since been taken down):

[http://blog.golang.org/real-go-projects-smarttwitter-and-
web...](http://blog.golang.org/real-go-projects-smarttwitter-and-webgo)

I don't program Go day-to-day any more (Meraki uses Rails and Scala), but it's
still my language of choice for personal stuff.

------
joeblubaugh
It's also worth checking out the gorilla library:
[http://www.gorillatoolkit.org/](http://www.gorillatoolkit.org/)

One thing I really like about gorilla is that it's broken up into pretty
sensible packages so you can pick and choose what you'd like.

------
jemeshsu
web.go is old and not maintained. If you're new to Go and wants a framework
check out beego
([https://github.com/astaxie/beego](https://github.com/astaxie/beego)). The
other popular framework is Revel which I think is "too heavy" and not my cup.

beego, revel are adaptation from other languages/framework, beego is
Python/Tornado inspired and Revel is Scala/Play inspired. beego is closer to
idiomatic Go than revel, i'm not expert but feel their MVC based structure
might not be "congruent" to Go's interface/composition construct. Sorry I
can't really explain what I meant, maybe Im just anti everything Rails like
MVC for web framework.

Many Gophers prefer to use light libraries such as Gorilla to assemble their
web apps, as Go already has basic http covered in standard library. Having
said that it is good idea in Go land to have a recommended template/structure
based on these light libraries for a best-practice web app that covers
standard web components that are outside of standard libraries such as
session, context, user auth etc. This is to make it quick to assemble an web
app with all essential, and a common code structure that makes maintenance
easy -> the advantages of a framework. Or maybe we do need to use a web
"framework" for Go after all. Similar reasoning on why people are using
Symphony/Laravel for PHP now.

Go is highly recommended for coding server backend components, the processing
and brain of app. But should one use Go for web front end? Go web
libraries/framework (beego/revel included) is not as matured as Rails/Django,
so you do need alot more of your own coding for a complete web ui front. Let
me break down:

* If you're are more business oriented and would like your web app up as fast as possible, use Rails/Django. I would still use Rails/Django even if your web app is only Rest API for a Angular/Ember app. You can then use Go to optimise your backend.

* If you would like to brush up your resume, by all means dip into Go for web app. As I predict it will help you 2/3 years down the road. I just noticed that irc #go-nuts has more members than ruby/rails. But then so is #haskell and yet Haskell is not as mainstream as PHP/Python/Ruby/Java.

* If you are already Rails/Django expert and am choosing between NodeJS and Go: keep on choosing as there is no clear advantage of one over the other. And you should also consider Clojure or even Scala. OK about Node vs Go for web app: NodeJS/ExpressJS has has more than a year advantage thus you see more NodeJS/ExpressJS projects. I think both are on par for time-to-market if you're developing a REST API.

* If you are novice programmer and new to web app, learn something like Rails/Django for web best practices. However because Go web library is close to metal, you will understand in greater detail on how web/http actually works by coding a web app and reading Go standard http library. You might heard that Rails/Django is passé and you might not want to waste time for something with "no future". But don't. Those are someone else opinion and Rails/Django will be around for many years to come. In fact Rails/Django is the top choice of many programmers who want to leave PHP/Java web. It is quite difficult nowadays to be a one language programmer. So pick up as main one that is current mainstream web technology (PHP, Rails/Ruby, Python/Django) and bet on one for future that is not as mainstream (Go, Clojure, Scala). It is harder for new programmer to pick up newer tech as far as learning materials go.

* If you are a superstar programmer, yes you do need to pick up Go, in addition to Haskell, Clojure, Scala, Erlang, Fortran, Basic and ARM assembly. Please do not learn go if you're a Javascript programmer who wears a Javascript t-shirt and has a Javascript soft toy (whatever) in your bed.

My 2.5 cents. To go or not to go?

------
henryw
What, a new framework in a new language? I haven't even learned ruby on rails
yet.

~~~
onedev
Hahaha join the club, I neither know Ruby nor Rails. Don't know Go either, or
Node, or Angular....I'm a dinosaur :)

~~~
tonyplee
me too!

Still making living from good old C.

"go" is just one letter too many to remember. :-)

------
russell_h
I love Go, but it seems like just about every HTTP request router is designed
around abuse of global state.

~~~
mvzink
It's not _designed_ around global state. It's true that just about every HTTP
router has this "feature", but all it's doing is allocating a "global" server
object by default and adding the module-level helper functions. In other
words, if you only want a single server object and don't need to configure it,
or if you just want a quick hello world example, you don't have to allocate
the server object yourself. Without those extra convenience methods, this
would be hello world's main:

    
    
        s := web.NewServer()
        s.Get("/(.*)", hello)
        s.Run("0.0.0.0:9999")
    

Same goes for net/http and gorilla. net/http calls it the "default" server,
web.go calls it the "main" server. I blame the influence of Sinatra etc.—the
examples (for all three libraries) don't make it clear that this is what's
going on and don't encourage making your own server objects to minimize global
state.

~~~
russell_h
Right, "designed" is probably a misleading way to put it. I just wish, like
you say, that libraries would stop supporting and encouraging use of global
routers.

------
tptacek
I'm not sure I see what this adds to the Go standard library and things like
Pat.

~~~
chimeracoder
Agreed - if you're new to programming in Go, I'd recommend using the standard
library (supplemented by Gorilla[0] once you get the hang of things).

 _If_ things start getting unwieldy as your app grows, you can always try out
something like Revel, but by starting with the standard library (which already
has a very clean web server built-in), you'll get a sense for the way things
work "under the hood" early-on.

If you want to see how a Go web server built with just the standard lib +
Gorilla looks, I wrote a simple sample application a while back:
[https://github.com/ChimeraCoder/go-server-
bootstrap](https://github.com/ChimeraCoder/go-server-bootstrap) . The most
verbose part is the oauth2 callback.

I should get around to updating it (it still even uses a Makefile! Eek!), but
it gives the basic idea.

(Sidenote: When did Github stop supporting the ".markdown" extension instead
of just ".md"?)

[0] [http://www.gorillatoolkit.org/](http://www.gorillatoolkit.org/)

------
jawr
Has anyone any tips on any frameworks for building JSON RESTful services? I
have been using [https://github.com/ant0ine/go-json-
rest](https://github.com/ant0ine/go-json-rest) and it works as a great
building block. Is there another great lib I have missed?

~~~
jackseviltwin
I took a look at a few of the go rest frameworks and settled on
[https://github.com/emicklei/go-restful](https://github.com/emicklei/go-
restful). It seems like it's the most feature complete and mature of the pack.
I'm playing around with a go-restful and gorp (orm-ish library in go)
combination at the moment.

I found this project
([https://github.com/jmcvetta/lgtts](https://github.com/jmcvetta/lgtts)) that
has managed to integrate go-restul/gorp and is also setup so it can be
deployed to heroku.

~~~
jawr
Thanks, go-restful looks awesome. Definitely going to play around with it!

------
0xfaded
One thing I don't like about these packages is the use of map[string] string
to represent dynamic url parameters. The conversion into a useful type seems
like something that could (and should?) be automatic.

Shameless plug: for my own use I wrote
[https://github.com/0xfaded/rhttp](https://github.com/0xfaded/rhttp) which is
used with (not a thin layer over) net/http. There is a draftish blog post to
go with this [http://blog.0xfaded.com/](http://blog.0xfaded.com/).

As a side note, I use an unusal pattern of passing an empty struct as a
function arguement for the sole purpose of being inspected using reflection.
Undecided if this is good or bad. Thoughts?

~~~
rogpeppe1
Nice package. I like the fact that it's limited in scope and actually does
some work for you. There's a trick you're missing though - you require the
user to pass in their expected params struct explicitly so you can reflect on
its type, but you _could_ just reflect on the handler function type itself.

Then a handler function could look like this:

    
    
        func Do(w http.ResponseWriter, r *http.Request, params *DoParams) {
             w.Write([]byte(params.Var))
        }
    

No need for any dynamic type coercion - it can all be checked up front when
the handlers are registered. The down side is that the signature of Handle
would become more opaque (its argument would just be an interface{}) and you'd
probably want to lose the Handler type.

FWIW, passing an empty struct for the sole purpose of being inspected using
reflection is not unusual (see for example gob.Register).

~~~
0xfaded
I'm aware of this, however there is a pretty serious downside: function
decorators (currying, whatever you want to call it) become difficult if type
information is encoded in the function signature. For example, I mark handlers
for logged in users by:

    
    
      handle(..., User(F))
    

The prototype of F and User might be

    
    
      func F(w http.ResponseWriter, r *http.Request, s *Session, i interface{})
      func User(...type of F...) func (http.ResponeWriter, r *http.Request, i interface{})
    

User() would do some preprocessing on the request and produce a Session for F.
The problem is that User accepts ...type of F...; although it could accept an
interface (of a function) but doing everything by reflection becomes
cumbersome.

This is one of the things I don't like about go but really you need a type
system like haskell's to achieve what I want here.

~~~
groks
You could create a dummy interface which all your DoParams-like types could
implement:

    
    
        type Params interface { IsParams() }
    

Also, you can get away with passing a nil pointer for reflection rather than
allocating a nil struct:

    
    
        fmt.Printf("nil pointer to DoParams: %T", (*DoParams)(nil))
        fmt.Printf("pointer to nil DoParams: %T", &DoParams{})
    

(Which isn't going to be a source of gc pressure in this instance, but
still...)

------
BookPage
I'm in a position where I've learned the basics of rails (can make very
primitive apps now!) and have completed the go-lang tutorial.

I love Go as a language and am itching to do something with it. Thing is, my
personal project is a webapp. I'd like to use Go for it but rails just seems
so much easier to make it happen.

Anyone have any thoughts or experiences actually making webapps with Go? It
feels like I'd be better off making tooling or API wrappers with Go rather
than the core webapp...

------
xacaxulu
As a newish Gopher, I really appreciate resources like this. It's especially
welcome after grokking The Way To Go (which is a great resource as well).
Great work!

~~~
somethingnew
Also be sure to check out [https://gobyexample.com/](https://gobyexample.com/)
It's so helpful!

------
chewxy
Is this the one that was inspired by web.py? When I started playing with Go, I
played with one called Web.Go, which was inspired by web.py.

~~~
marketer
Yes, it was definitely inspired by web.py (tornado, actually). I loved tornado
but didn't like the fact that there were no asynchronous libraries for it.

------
joeblau
What I want to see from go are more fleshed out frameworks like Rails,
Express, webapp2 etc. This still feels like a lot of boilerplate design is
left up to interpretation which is fine if you have a small time, but
considerably more frustrating as you scale and have to bring on new team
members.

------
elacey
It would be really useful for someone with experience developing in Go to
explain the pros/cons of using Go over alternatives. Why should I develop
websites in Go over Node or Python?

------
roskilli
Will be interesting to see the difference in how Go and Nodejs grow
considering the module system and time of reaching popularity will be similar

------
wilbertliu
It's the improvement of Go, isn't it?

------
waps
Does anyone know a simple way to get a go file webserver with traditional auth
(plain/digest) ?

~~~
cdoxsey
For the file server use the built in FileServer:

[http://golang.org/pkg/net/http/#FileServer](http://golang.org/pkg/net/http/#FileServer)

For authorization:

    
    
        var siteAuth = base64.StdEncoding.EncodeToString([]byte("USERNAME:PASSWORD"))
        func handle(w http.ResponseWriter, r *http.Request) {
            auth := r.Header.Get("Authorization")
            if auth != "Basic "+siteAuth {
                w.Header().Set("WWW-Authenticate", "Basic realm=\"REALM\"")
                http.Error(w, "Not Authorized", 401)
                return
    	}
        }
    

No real need for a library.

