
Web Development in Go - kevinburke
https://kev.inburke.com/kevin/go-web-development/?hn
======
atarian
>Compared with Ruby, PHP, Python, or Javascript, you're going to get great
memory and latency performance, and libraries that do what you expect.

Isn't picking a language to solve memory/latency issues a pre-optimization?
Also I'm not sure if one can argue that libraries from one particular language
are better at doing what you expect than libraries from another language.

Disclaimer: I'm trying to understand how much of what people are saying about
Go is hype. People are telling me things like you can cross-compile on
different platforms and output a binary, but I fail to see how these things
are important for most API's and web apps.

~~~
bhauer
I've written about this [1], but in brief, my opinion is that selecting a
high-performance platform is extremely reasonable, all else being equal (equal
familiarity with Go and Ruby, for example). Opting for a high-performance
platform allows you the freedom to build your application code in a genuinely
low-friction deferred-optimization manner.

Put another way, a high-performance platform provides a very high ceiling,
allowing your application to be more brute-force with its implementation. You
don't have to be sub-consciously worrying about performance gotchas while
implementing your code because a high-performance platform gives you _freedom
to be inefficient_ within your application domain.

Not only that, a high-performance platform postpones your first scale event,
and in some cases indefinitely defers it. I've found that applications on
high-performance platforms tend to be easier to deal with on a day-to-day
basis because they do not collect the various deployment performance-oriented
cruft that you typically see with low-performance systems. High-performance
platforms have simpler system architecture (fewer external processes, less
monitoring overhead, etc.)

A bonus is that the user experience will be just that much better thanks to
low-latency responses.

[1] [https://www.techempower.com/blog/2016/02/10/think-about-
perf...](https://www.techempower.com/blog/2016/02/10/think-about-performance-
before-building-a-web-application/)

~~~
nullnilvoid
The same argument can be made about C/C++, Java and Rust. These languages are
even more performant than Go in general. Why not choose them? Why Go?

~~~
jerf
For C/C++, don't use a memory-unsafe language to speak to networks. (The fact
that so many things already do is no excuse and adequate demonstration of why.
Also arguably _more_ true of C than C++ but I'm not particularly impressed
with claims that C++ is safe if you just "do it right" because that's the sort
of gap you can drive a truck through.) Rust is still a bit shy of web
libraries, and may be overkill for some use cases, but otherwise, go for it.
Go for it with Java too.

However, the performance gap between Go and Rust is much smaller than the gap
between Go and a dynamically-typed language, even one JIT'ed to the n'th
degree, and the gap between Go and Java generally lost in the noise [1].
Between Go, Java, and Rust, you've probably got a good case that you'll get to
more-or-less production-ready code fastest in Go. (And yes, "more-or-less" is
a gap big enough to drive a truck through too. I preemptively pretty much
agree with everything anybody might care to write about that issue in reply.
:) )

[1]: I suppose I should point out that a perf gap of 2 or 3 is "generally lost
in the noise". In the real world what tends to control which such language has
the better implementation of something for most tasks is who has taken more
time to write an optimized version. It's when you start getting up to the
10x-25x range that the gap between Go and a dynamic language can be that it's
not really "lost in the noise" anymore; in that case, the faster language can
end up simply faster than the slow language even if the slow language is given
a lot of extra love (assuming no "change to a different language"
shenanigans).

------
fideloper
I personally prefer whatever language/framework gets value out the door
quickest on the side of handling HTTP requests (e.g. rails or laravel for the
front-facing items) and something like Golang for plumbing or work that
requires speed/CPU optimization - queue workers, file manipulation, data
streaming, whatever.

Golang (and NodeJS) both feel really kludgy to me when getting into things
like handling form submissions (validating input, redirecting with
error/success messages, and all those tedious things that the popular
frameworks abstract away the best they can).

~~~
ksubedi
This. After using Go, Nodejs (Express, Koa), PHP (Laravel), Java (Spring) and
C# (Asp.Net Core), I realized that nothing beats me in productivity when I am
using Spring or Asp.Net core when building a web app. Little things like form
validation, route management, templating and a ton of little under the hood
stuff are much much easier with older frameworks that have been around for a
while.

~~~
cutler
Can you expand on how Spring or Asp.Net are better than Laravel with respect
to form validation, route management and templating which are generally
regarded as PHP's fote?

~~~
ksubedi
Laravel actually was great at form validation, route management and
templating, probably one of the best, however performance is what made me move
away from Laravel. With Spring and Asp.net Core, I got the best overall
development experience compared to the other ones I mentioned.

------
patrickmn
NaCl's secretbox for encrypting the session cookie - nice

------
weberc2
What's lacking in the HTTP library? The stock router isn't great, but it's
pluggable. Also, serving static files has never been a problem
http.StripPrefix("/tmp", http.FileServer(http.Dir("/tmp"))) (or something like
that, I forget the details). I guess I didn't find it very hard to get into
web development in Go with the standard library; I'm not sure there's enough
friction to justify diving into third party libraries. :/

~~~
kevinburke
> serving static files has never been a problem

I address this in the post; there's no problem with it, but it requires that
you (or your end users) come up with a solution for deploying static assets to
production, figuring out the relative paths between the working directory and
the asset directory, and ensuring that the right version of the binary loads
the right version of the assets. An example of the type of difficulty here is
that you couldn't remember how to do it off the top of your head.

If you compile them into the binary, you (or your users) don't have these
problems.

~~~
AYBABTME
I've always assumed that compiling assets into the binary meant the
http.FileServer can't use sendfile. I guess this means lower performance at
scale, but I've never verified if this actually happened or its effect.

~~~
jorams
When you serve files over https (which you always should) you can't use
sendfile anyway. The data will have to be encrypted, so you can't have the
kernel send the data straight into the socket.

~~~
blaenk
I hadn't considered this before but it seems to make sense. If I have nginx
configured with ssl and sendfile (X-Accel-Redirect) and my app sends an
X-Accel-Redirect response to nginx, you're saying that it's not actually using
sendfile under the hood?

~~~
inimino
Sendfile is just a kernel feature for directly sending a file to a socket. If
you are doing literally anything other than just sending the raw bytes of the
file over the network, it can't be used.

~~~
blaenk
Yeah I'm aware that it's a system call that only knows about file descriptors.
It's just that it just now hit me that a consequence of that is that a web
server configured to use ssl _and_ sendfile isn't really using sendfile, short
of some hairy hack of writing/encrypting the response into a file (maybe in-
memory with something like memfd_create) and using sendfile on that, which
would defeat the purpose of avoiding user-space entirely.

------
Gonzih
What about templating, middlewares, security, authentication, authorization?
Do I need to glue this from custom libraries to the web server myself every
time I start a new project?

~~~
kevinburke
\- there's a templating example in the project

\- there are middleware examples in the blog post and in the project

\- depends on what you mean by "sucurity". there's an example of secure cookie
encryption in the blog post and the project

\- depends on what sort of authentication or authorization you need. If you
just need basic auth you can try
[https://godoc.org/github.com/kevinburke/handlers#BasicAuth](https://godoc.org/github.com/kevinburke/handlers#BasicAuth)

~~~
Gonzih
\- ok, i did not look at example, sorry \- for logging, but thats not enough
\- thanks for pointing out typo in an interesting way, yeah but blogpost just
mentions custom library that should be glued to your webserver \- custom
library again glued to the server on every project

I would go for new projects with something different than go. Like scala. Go
is great for rest apis, but once your app becomes more "complete" in terms of
requirements go becomes more and more painful in my experience.

~~~
kevinburke
> I would go for new projects with something different than go.

You should probably write your own article then.

------
positr0n
Is the flash message setup a standard way implement that type of
functionality?? Encrypting the cookie with a key that is delivered client side
anyway seems like it doesn't buy you anything.

~~~
kevinburke
The key isn't sent to the client.

You can set the flash message in plain text, but I'd rather avoid the
possibility of tampering, and it lets me reuse the same cookie code I use to
encrypt e.g. session tokens.

~~~
slrz
What kind of tampering are you thinking about here? Aren't those messages sent
from the server to the client? Thus, in-transit tampering should be prevented
by TLS.

If the key isn't sent to the client, how is the client supposed to display
that message? Why are these messages encoded into a cookie in the first place?
I don't think I understand the concept.

~~~
kevinburke
The message is read on the server as part of the next request and then
displayed in the appropriate spot in thr UI

------
meow_mix
How good are the ORMs options in Go? One of the reasons Rails is my go-to for
web development is how easy Active Record it makes configuration and changing
databases.

~~~
segmondy
How many times have you changed databases in your production apps or are you
building and selling software and wanting users to be able to pick their own
database?

~~~
ksubedi
I don't think that is the only reason to use ORM's. They definitely help me be
more productive while building apps where super-high performance is not an
issue.

------
conroy
On the subject of Go web development, I'll plug one of my favorite libraries:
[https://goji.io](https://goji.io). It's a super-fast HTTP router that
supports middleware and pattern matching.

~~~
brightball
This is, IMHO, the PHP/Javascript problem showing up in Go.

All 3 languages have so much bundled in for web development out of the box
that it's too easy to create frameworks...so there are lots of them without
any type of rallying standard.

That's one of the reasons that I'm really averse to Go for web development
that isn't just API based because you gain a lot from a complete, primary
framework for web projects.

It's one of the things that makes Elixir so appealing because you've got a
clear next-gen-web winner in Phoenix with a language that brings you so much
of what's good about Go due to it's Erlang/BEAM underpinnings.

~~~
always_good
You're just looking at one set of trade-offs and mistaking it for the best.

Since people do not unanimously use large batteries-included frameworks, you
must realize that some people prefer some batteries a la carte.

Rails and Phoenix may win the large framework space, but they certainly don't
win the web space.

~~~
brightball
Never said it was the best, just that there are a lot of pain points that come
from trying to use Go for a full stack development experience.

Command line, workers, network and api layers are GREAT. If you have something
that needs a custom solution...great. But the experience around managing a
polished view layer, assets, routing, middleware, sessions, routing,
redirects, migrations, database access, etc can get fragmented and tedious
when roll-your-own becomes the defacto mode of operation.

When a language doesn't have all of the web-native stuff built in by default
(like PHP, JS and Go) the community around the language tends to organize
around a framework experience that will eventually lead to a common
development experience that people can further develop tooling around.

It's not a knock on Go itself, it's just something that creates a noticeable
side effect in the community in terms of fragmentation. People clearly WANT
frameworks, because they keep rebuilding them. Doesn't mean you always need
one, but it does mean that having a "winner" could be good for the community.

------
hasenj
Does go have any advantage over other compiled languages, like say, swift?

For example: [https://vapor.codes](https://vapor.codes)

~~~
kevinburke
That's a question with a pretty broad answer. Each language has its own set of
tradeoffs and things that it values most highly.

In particular Go is shaped by the experience of needing to run high-
performance servers at a company with thousands of engineers; it was designed
to address a lot of the problems with running C++ or Python in that
environment.

Swift came from Apple, and was designed to address a lot of the problems with
writing mobile apps in Objective-C.

~~~
kenshi
I don't think Swift was designed to address the problems of writing mobile
apps in Objective-C.

It seems more like a compiler/language developer's idea of what a good modern
language should be.

~~~
rokob
[http://carlosicaza.com/swiftbooks/SwiftLanguage.pdf](http://carlosicaza.com/swiftbooks/SwiftLanguage.pdf)

Swift was designed for writing apps on the mac platforms, primarily on iOS,
and although somewhat debatable as a replacement for Objective-C due to it's
quirks. If you want proof of that, just read between the lines in the original
documentation.

Not to mention, many of the features that were called out originally are
direct responses to issues with Objective-C: Optionals, Typed containers,
Generics, modules, real first class functions instead of just blocks, final
classes, let, etc.

~~~
coldtea
> _If you want proof of that, just read between the lines in the original
> documentation._

Those things were obviously requirements for roles it should fulfill.

But no things in its design hold it back from being a modern language that's
even more expressive and fast than Go. Except some concurrency love perhaps.

------
update
> You should write your next web server in Go

Are people writing their own web servers these days? is that a thing? Seems
like everyone uses nginx.

~~~
vfaronov
“Your own web server” here doesn’t mean “your own program that reads from
sockets and parses HTTP” — that is taken care of by Go’s standard library.

“Your own web server” here means “your own program that serves HTTP requests”,
and yes, people write programs like that all the time.

~~~
update
I read the post. The language is just confusing. You shouldn't have to tell me
that "You should write your next web server in Go" doesn't mean what it says
on the tin.

A web server is Apache, Nginx, Lighttpd, etc. What you just described is a Web
Application, which I develop all the time on python -> uwsgi -> nginx stack.

For the record, I'm not blaming you, but the author for the confusing
language. The title says "Web Development in Go" \-- web dev is traditionally
web applications/html/css etc, not typically including servers. Then their
opening sentence is "You should write your next web SERVER in Go"

/pedant

~~~
tps5
I don't think the language is the slightest bit confusing. I also think your
definition of "web server" is wrong. I would say a web server is a program
that processes HTTP requests and optionally responds with something (commonly
HTML, but can respond with data of any format).

That includes apache, nginx, etc. It also includes programs written in X
language that process HTTP requests.

