
Ask HN: What is the current state of web frameworks in Golang? - freedomben
There are quite a few different web frameworks for Go, as well as just the built in `net&#x2F;http`.  Has any one package emerged as more common or standard than others?<p>What are you currently using?  Do you like it?
======
everdev
The common reply in the Go community is "don't use a framework" or "roll your
own".

The idea is that small packages suited to individual tasks are a better
solution than a large framework package that includes more than you need, or
tried to for your use case into a shared, common use case.

IMO, frameworks are great for rapid prototyping, but in Go and it's explicit
programming style, most devs prefer to build most by have and only import a
minimal number of packages for specific tasks.

~~~
bigdubs
Some common helpers are nice though, not sure that constitutes a framework but
it definitely saves time not having to rewrite response compression and
logging.

------
jjude
Nobody has mentioned beego [1]. You can write a decent web-application using
core Golang language. Yet, coding large applications require many features,
like session handling, db connection, and so on. Instead of composing these
from independent sources, you can use Beego which comes bundled with all of
these.

If you are aware of Python ecosystem Beego is like Django (though Beego
doesn't have an admin module).

I have been using Beego for couple of years now for my personal projects. I'm
happy with it. It has almost all the features required for a web-application
framework. It has good documentation too.

Just yesterday I released a side-project sheet2buffer[2], coded in Beego as
backend and React as front-end.

If you are interested, I also wrote an introductory post about Beego[3].

[1]: [https://beego.me/](https://beego.me/) [2]:
[https://sheet2buffer.com/](https://sheet2buffer.com/) [3]:
[https://jjude.com/beego-intro/](https://jjude.com/beego-intro/)

------
AdamJacobMuller
I started a project about a year ago and I specifically wanted to answer this
question. As a result, I wrote that project in revel.

Ultimately I don't hate revel and the result is an operational system today. I
don't exactly regret the decision to use revel, but I also think that revel
ultimately didn't bring many useful things to the party. I do know I'd have a
better, more extensible easier to understand application if I had not used
revel. I do know that if I was just using standard net/http I would have
developed things faster. I found myself more often fighting against the
framework to bend it to my will than benefitting from it.

All that said, I don't think I would have the confidence that "just use
net/http" is the correct answer had I not done a project in revel.

I did a few projects before and after and in-between the revel project, while
still actively developing and maintaining the revel project. Ultimately, I now
find myself dreading working on the revel project to the point where, when I
have time to spare, I'm much more likely to work on one of the non-revel
projects.

~~~
GolDDranks
I just started a project with Revel.

I dabbled with Go some years ago, and I was excited to try it again because I
like statically typed languages and the simplicity of Go.

However, the package management story was insane. I had really hard time with
that. Fortunately they are acknowledging the problems and fixing them.

Also, I kept missing Rust-style error handling. I've been programming in Rust
extensively for a few years, and I thought Go might provide benefits of being
"a simpler (garbage-collected) Rust". However, I keep longing some nice things
from Rust.

Revel was... Ok. The fact that it builds the code while it's running is nice
for rapid prototyping, but it was also really hard to fix if/when it didn't
work. (
[https://github.com/revel/revel/issues/1349](https://github.com/revel/revel/issues/1349)
)

I found the default template engine to be a bit lackluster – template
inheritance is the basic pattern I'd like to see everywhere as the default,
but it didn't support that.

The project is still in an early phase so it's hard to say more than that.

------
astockwell
After building apps in Martini and Revel, I’ve moved to using a smattering of
decent (IMHO) packages good at 1 thing:

Let me render templates in a layout file with `yield` -
[https://github.com/unrolled/render](https://github.com/unrolled/render)

Let me quickly route with param support -
[https://github.com/julienschmidt/httprouter](https://github.com/julienschmidt/httprouter)

Sessions, flash messages, and secure cookies -
[http://www.gorillatoolkit.org/pkg/sessions](http://www.gorillatoolkit.org/pkg/sessions)

POST parameter-to-structure binding (this is optional and easy enough to do by
hand) - [https://github.com/mholt/binding](https://github.com/mholt/binding)

I write my own middlewares for logging, auth, etc. Use viper for
configuration, gorm for an ORM, and for anything more complicated, accept that
you’re about to learn a whole lot about it because you’re gonna be writing it
yourself.

~~~
astockwell
OH! And json-to-go people, use json-to-go. Thank me (well, mholt really)
later!

~~~
guessmyname
Here is a link for the lazy [1].

@mholt also created curl-to-go [2].

[1] [https://mholt.github.io/json-to-go/](https://mholt.github.io/json-to-go/)

[2] [https://mholt.github.io/curl-to-go/](https://mholt.github.io/curl-to-go/)

------
ereyes01
To each their own, but I personally prefer the lego-building block-approach
instead of the kitchen-sink approach of bigger frameworks. In Go at least,
this scales quite nicely with your code IMO.

I use a couple of thin layers over net/http:

Gorilla mux: [https://github.com/gorilla/mux](https://github.com/gorilla/mux)

... Gets me easy route params and HTTP method filtering.

Negroni for middleware:
[https://github.com/urfave/negroni](https://github.com/urfave/negroni)

... Super easy to roll your own, plus there's a bunch of random off-the-shelf
middlewares that people have put together (see their README).

For talking with my DB, I just use sqlx (and sqlmock in my unit tests).

[https://github.com/jmoiron/sqlx](https://github.com/jmoiron/sqlx)
[https://github.com/DATA-DOG/go-sqlmock](https://github.com/DATA-DOG/go-
sqlmock)

------
deklerk
I generally just stick to net/http. In both small projects and large
enterprise-y projects it's served well. I think most Go devs are roughly of
similar opinion at this point.

------
artursapek
gin[1] is a popular off-the-shelf solution that provides a lot of
functionality for you. But as everdev said, it's pretty normal to gradually
build up your own stack using the stdlib and possibly some smaller, more
focused packages like httprouter[2] and the gorilla toolkit[3].

I actually have learned a lot about HTTP/HTTPS servers by working on a lower
level and building up my stack! I recommend just starting with the stdlib and
importing 3rd party code where you feel yourself limited by it. The first
thing people probably adopt is a more expressive router.

[1] [https://github.com/gin-gonic/gin](https://github.com/gin-gonic/gin)

[2]
[https://github.com/julienschmidt/httprouter](https://github.com/julienschmidt/httprouter)

[3] [https://github.com/gorilla](https://github.com/gorilla)

------
anschwa
While I'd agree that net/http is very capable, it still comes with a variety
of gotchas when doing timeouts, logging, routing, etc. I think gin[1] is a
good bet for jumping into building something without having to dive into doing
a lot of http.Server research.

[1] [https://github.com/gin-gonic/gin](https://github.com/gin-gonic/gin)

~~~
qrv3w
Also love Gin - I've used this for maybe a dozen different projects. Sometimes
I use the stdlib but when I do I usually end up trying to make an API like
Gin. Gin just makes things so much faster to write good looking and well-
performing code with their contexts and simple API.

My favorite thing about Gin: its README has 90% of what you need to know, with
refined examples. I love when README's are so expressive, especially when
Gitlab/Github/Bitbucket make the README the front page. Also, the README comes
with the code when you clone so you can easily refer to it offline (I realize
you could generate Godocs but I always forget the command to do this, and
Godocs don't often have nice examples).

I'll also point out that Gin has an excellent collection of contributed
middleware [1].

[1]: [https://github.com/gin-gonic/contrib](https://github.com/gin-
gonic/contrib)

------
judWhite
I've used Gorilla
[http://www.gorillatoolkit.org](http://www.gorillatoolkit.org) for 4+ years
and I'm happy with it. It follows the signatures of net/http and routing is
easier than regex.

------
nerdywordy
I'm surprised there isn't more about Buffalo in this thread. It's creator
(Mark Bates) has stated inspiration from the rails world, but has focused on
building Buffalo to be very flexible.

It provides a nice boiler plate for the modern web app and pulls together a
lot of the single packages mentioned here so you don't have to worry about
wiring things together.

I've built a few small apps with it and thoroughly enjoyed the dev process.

(GoBuffalo.io)

------
someone13
I really like chi[0] - I think it strikes the right balance of being small and
understandable, but also solving common problems (e.g. nested routes, URL
parameters, etc.). It also uses standard Go conventions, so it's very
interoperable and would be easy to migrate away from, if necessary.

[0]: [https://github.com/go-chi/chi](https://github.com/go-chi/chi)

~~~
AdamJacobMuller
chi is cool, but, isn't really a framework. Chi is just a router and that's a
lot of why I think `chi` is quite good.

I happen to be a fan of web[0] even though its basically a dead project, it
works fine and is minimal enough to not need any changes.

[0] [https://github.com/gocraft/web](https://github.com/gocraft/web)

~~~
ovao
While chi is ‘just a router’ (and an exceptionally good one at that), it also
includes a number of particularly useful middleware.

~~~
AdamJacobMuller
I don't mean to say "merely" a router. I think its good because it does one
thing well.

------
101km
I'll cautiously mention:
[https://github.com/valyala/fasthttp](https://github.com/valyala/fasthttp)

It's a net/http replacement that is close to x10 in performance -- however it
is not a drop in replacement and you should avoid it unless you really
actually need the rps.

That's pretty much the opposite of a web framework.

------
jeevatkm
I would like to mention aah framework [1], Documentation [2], Examples [3];
have a look and see. Does it match with your direction and project needs. I'm
looking forward to your candid feedback.

Personally I would say it depends on your project needs, timeline, etc.
Whether you're gonna use framework or roll your own.

My suggestion is to take your time to evaluate the frameworks and select the
one which satisfy you the most. Generally none-of-the-framework would cover
100% of project needs; including aah.

Disclaimer: I'm the author aah framework.

[1]: [https://aahframework.org](https://aahframework.org) [2]:
[https://docs.aahframework.org](https://docs.aahframework.org) [3]:
[https://github.com/go-aah/examples](https://github.com/go-aah/examples)

------
karanbhangui
I've been using echo[0] and sqlx[1]. I like it because it's performant and
idiomatic.

It is minimalist compared to Rails or Django, but appropriately designed for
the go world where you roll your own on top of tightly scoped libraries.

[0]: [https://echo.labstack.com/](https://echo.labstack.com/)

[1]: [https://github.com/jmoiron/sqlx](https://github.com/jmoiron/sqlx)

------
siquick
Excuse my ignorance but does Go store libraries locally, in the way other
package managers like NPM and Pip do?

I just looked at some Go source code and it references Github repos?

e.g.

> import "github.com/astaxie/beego"

Can I clone that repo into local and then import that? I wouldn't like to run
a project at the mercy of someone elses remote repo.

~~~
stephenwithav
You have to use a vendoring tool like Glide[1] for now, but Go is actively
testing official vendoring support with vgo[2], where you use git tags for
versions.

1\. [https://glide.sh/](https://glide.sh/) 2\.
[https://github.com/golang/go/wiki/PackageManagementTools](https://github.com/golang/go/wiki/PackageManagementTools)

------
devj
Check out GoKit - [https://gokit.io](https://gokit.io)

"Go kit is a programming toolkit for building microservices (or elegant
monoliths) in Go. We solve common problems in distributed systems and
application architecture so you can focus on delivering business value."

------
jstewartmobile
net/http

I started with a more "batteries included" framework. There were too many
impedance mismatches between the framework and other libraries. Having to
whittle almost every 3rd-party library to fit within the framework was not
worth the effort.

Switched to net/http and haven't looked back.

------
hendry
For database CRUD mappings to Web APIs, are the there any solutions ?

------
nostalgeek
There is no real good framework and anybody can write a trie based router in 2
hours:

[https://vluxe.io/golang-router.html](https://vluxe.io/golang-router.html)

However, Go ecosystem is starting to look interesting library-wise, as long as
your project doesn't involve enterprise integration with legacy XML services
or SOAP, because Go sucks at mostly anything XML.

For templating I use Jet because the standard templating library is too basic
for professional use
[https://github.com/CloudyKit/jet](https://github.com/CloudyKit/jet) .

I don't use ORM, I use
[https://github.com/Masterminds/squirrel](https://github.com/Masterminds/squirrel)
for query building and
[https://github.com/jmoiron/sqlx](https://github.com/jmoiron/sqlx) which helps
deals with row<=>struct conversion. For database migrations, I use
[https://github.com/rubenv/sql-migrate](https://github.com/rubenv/sql-migrate)
, but if you need an ORM gorm
[https://github.com/jinzhu/gorm](https://github.com/jinzhu/gorm) is OK if you
do code first and sqlboiler
[https://github.com/volatiletech/sqlboiler](https://github.com/volatiletech/sqlboiler)
is OK if you do database first.

For session handling I use scs github.com/alexedwards/scs , for converting
form encoded data to go structs I use github.com/gorilla/schema, for logging I
use zap [https://github.com/uber-go/zap](https://github.com/uber-go/zap). For
managing roles in an app I use either the voter pattern
[https://symfony.com/doc/current/security/voters.html](https://symfony.com/doc/current/security/voters.html)
in simple cases or casbin github.com/casbin/casbin . For background jobs I
used [https://github.com/gocraft/work](https://github.com/gocraft/work) and
[https://github.com/gocelery/gocelery](https://github.com/gocelery/gocelery) ,
for caching i just use redis [https://github.com/go-
redis/redis](https://github.com/go-redis/redis) , for data validation I used
[https://github.com/asaskevich/govalidator](https://github.com/asaskevich/govalidator)
or [https://github.com/go-ozzo/ozzo-validation](https://github.com/go-
ozzo/ozzo-validation) . For sending mails to customers I used
[https://github.com/go-gomail/gomail](https://github.com/go-gomail/gomail)

If i need html forms, I first describe form elements as a struct then write
form helpers in jet templating to display them like that:

    
    
        type LoginForm struct {
                Login, Password string
                Form
        }
    
        func (form *LoginForm) validate(r *http.Request) error {
                r.ParseForm()
                form.Decoder().Decode(form, r.Form)
                form.Errors = map[string][]string{}
                if err := (requiredValidator{}).validate(form.Login); err != nil {
                        form.Errors["Login"] = append(form.Errors["Login"], err.Error())
                }
                if err := (requiredValidator{}).validate(form.Password); err != nil {
                        form.Errors["Password"] = append(form.Errors["Password"], err.Error())
                }
                return form.getErrors()
        }
        func (form LoginForm) LoginFormView() LoginFormView {
                return LoginFormView{Fields: []Field{
                        {Name: "Login", Label: "Email", Type: "text", Value: form.Login, Required: true, Errors: form.Errors["Login"]},
                        {Name: "Password", Label: "Password", Type: "password", Value: form.Password, Required: true, Errors: form.Errors["Password"]},
                        {Type: "submit", Value: "Submit", Required: true},
                        {Type: "reset", Value: "Reset", Required: true},
                }, Method: "POST", Name: "LoginForm"}
        }
    

Then I can just write an helper in jet to display the the form view:

    
    
        {* tag attributes *}
        {{ block attributes() }}
            {{range .}}
                {{.Key}}="{{.Value}}"
            {{end}}
        {{ end }}
        {* form field *}
        {{block field()}}
        <label>
            {{.Label}}
            <br/>
            {{if .Type == "textarea" }}
            {* textarea *}
            <textarea  name="{{.Name}}" {{ yield attributes() .Attributes }} >{{.Value}}</textarea>
            {{ else if .Type == "select" }}
            {* select *}
            <select name="{{.Name}}" {{yield attributes() .Attributes }}>
                {{ range .Options }}
                <option value="{{.Value}}" {{ if .Selected }} selected {{ end }}>{{.Label}}</option>
                {{ end }}
            </select>
            {{ else }}
            {* basic input *}
            <input type="{{.Type}}" name="{{.Name}}" {{ if isset(.Value) }} value="{{.Value}}" {{ end }}
            {{ yield attributes() .Attributes }} {{ if .Checked == true }} checked {{end}} />
            {{ end }}
        </label>
        {{end}}
        {* form template *}
        {{block form()}}
        <form action="{{.Action}}" name="{{.Name}}" method="{{.Method}}">
            <fieldset>
                {{ range .Fields }} {{yield field() .}} {{end}}
            </fieldset>
        </form>
        {{end}}
    

This is the exact app structure I use to deal with dependencies and filters :

[https://medium.com/statuscode/how-i-write-go-http-
services-a...](https://medium.com/statuscode/how-i-write-go-http-services-
after-seven-years-37c208122831)

~~~
jeevatkm
You have written your experience in detail.

If you don't mind. I would like to request you to have a look aah framework
[1]? and share your candid feedback. I'm interested in your viewpoint. I'm the
author of aah.

[1]: [https://aahframework.org](https://aahframework.org)

------
rishav_sharan
Buffalo is an amazing kitchen-sink framework for go. Echo, is another great
one though it is much more minimalistic

------
anaganisk
What about iris? All i see I propoganda in its docs. Is it what it actually
claims?

~~~
guessmyname
DO NOT USE IRIS [1][2][3][4]

The author of this framework, who calls himself Kataras, is very unethical.

He fell into a big controversy with the management of his repositories,
stealing several chunks of code from other popular projects without giving
credits to their respective authors, and then using them to write benchmarks
to make his own project look better than it is. He also spent several months
creating bots to upvote his articles on different news aggregators and _star_
his repositories to increase visibility in the GitHub Trending page. He also
created several accounts in different websites _(mostly Reddit)_ to act as a
supporter of himself. The last time I heard about him, he had forked his own
repositories multiple times to re-brand Iris with other names, hoping that
people wouldn't notice, specially people who are just starting using Go.

[1]
[https://www.reddit.com/r/golang/comments/57tmp1/why_you_shou...](https://www.reddit.com/r/golang/comments/57tmp1/why_you_should_not_use_iris_for_your_go_projects/)

[2] [http://www.florinpatan.ro/2016/10/why-you-should-not-use-
iri...](http://www.florinpatan.ro/2016/10/why-you-should-not-use-iris-for-
your-go.html)

[3]
[https://www.reddit.com/r/golang/comments/57w79c/why_you_real...](https://www.reddit.com/r/golang/comments/57w79c/why_you_really_should_stop_using_iris/)

[4] [https://github.com/avelino/awesome-
go/pull/1137](https://github.com/avelino/awesome-go/pull/1137)

------
wpdev_63
does their package manager still suck?

------
mlevental
web frameworks aside what's really missing an ORM. i'll get excoriated for
even suggesting that i shouldn't just use sqlx or whatever but using
django/python makes me hate using go for web backends.

~~~
swah
Me, an intellectual: "Yeah, so I prefer to write my own SQL so I know what is
going on behind the scenes..."

And then 99% of that _hardcore SQL_ is just:

    
    
        INSERT INTO users(name,email,password_hash,address1,address2,postalcode,city,country,created_at,updated_at) VALUES ($1,$2,$3,$4,$5,$6...)
    

Yeah, I'll try an ORM next time.

