

Why I wrote gocraft/web - cypriss
https://developer.uservoice.com/blog/2013/12/12/why-i-wrote-gocraft-web/

======
druska
You never mentioned martini
[https://github.com/codegangsta/martini](https://github.com/codegangsta/martini)

~~~
cypriss
As another commenter mentioned, I learned about Martini midway through writing
this.

I really like Martini - if it existed a bit earlier, I probably would have
just used it and been happy.

That being said, there are some differences between the packages. First,
Martini has great plugin support because 3rd parties can inject their
arbitrary type into handlers. On the other hand, gocraft/web has nested
routers and middleware, which are really important for my own projects.

This may be temporary, but gocraft/web also has faster performance because it
does less reflection, and because it's router is O(log(N)) instead of O(N).
(See [https://github.com/cypriss/golang-mux-
benchmark](https://github.com/cypriss/golang-mux-benchmark) , especially as
you add more routes).

Finally, I prefer a more consistent signature to my handlers. Martini
optimizes for flexibility. And depending on how much you want to inject into
your handlers, your argument list can get really long.

Overall, I think Martini is absolutely great and think it's one of the best Go
web libs out there.

~~~
recuter
So Gocraft/web stays around ~4ms no matter how many routes you throw at it
essentially but Martini and others are ~20ms and sometimes much more? That can
really add up.

Most web apps don't have quite so many routes typically but its not
unreasonable and I'm surprised routing is allowed to get so expensive in the
other frameworks. Kudos to you, I was psyched about Martini so I'm going to
see about fixing that for it at least.

Edit: D'oh. Need coffee. No wonder it looked really bad to me, up to 70ms to
do routing is abhorrent. Carry on. :)

~~~
druska
Additionally, some of these libs are unoptimized and performance will change
with time. Either way, since the performance differences are so small, it's
probably best to go with what's easiest to work with.

------
nemothekid
I've been using go for some time but I've never seen this:

    
    
        Get("/hello", (*Context).SayHello)
    

What is going on here? How is (*Context).SayHello being called?

~~~
ghayes
I'm new to this syntax too, but I believe it's just a reference to the
function `SayHello` as defined on the `Context*` type. That is, if you have:

    
    
        func FuncA() { } // normal function
        func (int) FuncB() { } // function on an int object
    

You could later reference those functions via:

    
    
       var func1 := FuncA // assign FuncA into func1 var
       var func2 := (int).FuncB // assign FuncB into func2 var
    

But again, I'm just piecing that together from context and haven't looked at
the spec.

~~~
recuter
So you're (ab?)using this to peg middleware functions on the context object?
Why do it like that?

------
bicknergseng
>>For instance, in Revel you need to put your controllers in a package called
‘controllers’, and models in a package named ‘models’. Nope!

I'd love some opinions on this. I prefer separating models/views/controllers,
but have recently seen some mvc apps where models/views/controllers are
grouped together by function/name. Thoughts on the traditional MVC directory
structure vs alternatives?

~~~
bgaluszka
> but have recently seen some mvc apps where models/views/controllers are
> grouped together by function/name

Can you put links to some of those apps that use that approach?

------
dreamdu5t
Just curious, but why have request be different from context? The request _is_
the context.

~~~
regecks
While using gocraft/web I've slowly come to the realization that it would be
very convenient if the Context already knew about the Request and Response
(without me having to pass web.ResponseWriter everywhere).

