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]
From very quickly playing with it for a toy app, Revel is impressively easy to get started with. I do agree with elithrar that some things don't seem quite "Go-y" (variable names passed to Render turn into template data names...how?), and it sort of makes you say "huh" that today's 4 years of Go post mentions Gorilla and not Revel. Even in my short time playing wiht it part of me kind of wanted to go back to net/http to not use magic I didn't understand. Maybe that part would prefer Gorilla. But, anyway, if Gorilla is a better alternative to Revel, Go does not lack for decent Web toolkits. :)
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) - a well-maintained, active project if you want to head down the framework route. Closer to Sinatra/Flask than Django/Rails.
• 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.
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.
> Does not compute. I'm fairly sure you're a programmer mate.
I should clarify: it's not my day job. Most of my "programming" experience has been hacking small Python things together. I do understand web security though, and a CSRF package certainly isn't a massive undertaking (it does require rigor, though).
> 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.
> 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.
Thanks. I still don't see how that's fundamentally different from JVM or .NET languages though. Sure, your jars or asseblies might be more than one file, but they're all in the same directory. Deploy means upload the contents of that directory.
With some clever compilation stuff, you can also pack most static assets directly in your application (see https://github.com/jteeuwen/go-bindata ). This gets even more magic...
In Scala there's also an option to pack you application in a large package and distribute. It's quite a popular approach. We can use tools for this like https://github.com/xerial/sbt-pack
> I wouldn't recommend Revel to many (it's Play heritage isn't well suited to Go, IMO)
Can you elaborate on the issues you've had? I've used Revel on one project and it was totally adequate. The automatic reloading works well, and I built a reasonably complex data warehousing app in a few days with it. Other than some awkwardness in deployment and lack of built-in CSRF filter it seems great!
I have mixed feelings about this. On the one hand its true that there are a lot of abandoned libraries out there, but on the other Go isn't like node.js. They don't reinvent the wheel with every release, and changes have been very conservative (and they have tools to automatically upgrade your code for you).
In general Go libraries are at their best when they follow the unix philosophy: Write programs that do one thing and do it well. Those programs, even after being abandoned for years, still work fine. (for example: https://github.com/dchest/siphash)
They're at their most brittle when they are highly platform dependent (like bindings to some C libraries) or massive never-finished frameworks.
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):
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.
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.
I am new to Go, but have dived right in and rewriting our current PHP backend in Go.
This global state abuse sounds quite important to understand. Unfortunately I do not have any clue what you are talking about. Could you point me in a direction of some examples of someone doing it the right way?
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 . 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"?)
web.go provides a request context, some helper functions (Slug, Urlencode, etc) and so on. pat (if you mean http://www.gorillatoolkit.org/pkg/pat) is "just" a mux/router—although a really nice one.
However, gorilla/pat + gorilla/context + gorilla/sessions* are, IMO, much more flexible than web.go and don't unnecessarily rewrite the wheel as much as web.go tries to. They also plug together easily: there's really no "glue" you have to manage. Just import them and use them as you would.
* web.go pretty much forces you to use cookies. gorilla/sessions can use a cookie store, a filesystem store, Redis (my pick) or the other stores out there (CouchBase, mySQL) thanks to the store API the package provides.
I didn't see whether this library handles a middleware layer, but that is the reason I use Slim for my web applications despite PHP having first class support for that sort of stuff already.
Has anyone any tips on any frameworks for building JSON RESTful services? I have been using https://github.com/ant0ine/go-json-rest and it works as a great building block. Is there another great lib I have missed?
I took a look at a few of the go rest frameworks and settled on 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) that has managed to integrate go-restul/gorp and is also setup so it can be deployed to heroku.
I think that there is a big opportunity in using Google Discovery style REST APIs. There is a new framework at github.com/rwl/endpoints that lets you build "Cloud Endpoints" style REST APIs outside of the Appengine ecosystem. Here is an example application using this project: https://github.com/philips/endpoint-hello
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.
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?
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).
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.
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...
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!
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.
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.
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?
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). 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.
1. http://robfig.github.io/revel/
2. http://www.gorillatoolkit.org/