

Thoughts on Go after writing 3 websites - kkowalczyk
http://blog.kowalczyk.info/article/uvw2/Thoughts-on-Go-after-writing-3-websites.html

======
hvs
I've just worked my way through the Go Tour and have begun working on my first
real project in it (a basic wiki, for learning purposes). At first, I was
expecting C with some syntax changes, but the changes made feel like they were
almost entirely made for legitimate reasons. Types definitions after variable
names really does make sense when you start to use it. Even with my limited
experience in it, I can say that it is really a joy to develop in.

------
lazyjones
Thanks for posting this, the code is very readable and good for learning. How
much time did you spend on Go before you finished these projects?

~~~
kkowalczyk
I can't really quantify it as it was in drips but in general, since I already
knew C and Python, learning Go was easy. I could have started to write a web
app right away, following tutorials on Go website and elsewhere.

At the beginning it's frustratingly slow, as it always is when you learn
something new, but if you know other C-like languages, picking up Go will be
fast. You just have to put the time to learn standard library and Go way of
doing some things.

~~~
mitchi
I have some questions. Are you on Linux or Windows? Did you have to use a
debugger or no need?

~~~
rartichoke
Go has full support for gdb if you want a debugger. You can even hook into go
routines.

------
chimeracoder
> If you know the shape of [JSON] data, you can serialize (marshal, in Go’s
> parlance) data structures to JSON or XML and de-serialize (unmarshal) from
> JSON or XML into a struct.

I wrote a short script to automate generating the struct definitions, since I
didn't want to generate the structs by hand. Go's reflection made this really
easy.

<https://github.com/chimeracoder/gojson>

~~~
lucian303
PHP has json_decode() and json_encode() which do all of this correctly ... GO
is interesting, but production ready? Not for awhile.

~~~
agentS
Package encoding/json from the standard library can decode to objects
("Object" in the Java sense, "void *" in the C++ sense) like json_decode does.

It also can decode directly into typed structures. An example from the
documentation (you'll have to open the linked example):
<http://golang.org/pkg/encoding/json/#example_Decoder>

Anecdotally, a typed version of JSON decoding is much nicer to work with.

~~~
lucian303
"Anecdotally, a typed version of JSON decoding is much nicer to work with."

How so? Considering that JSON isn't strongly typed.

~~~
agentS
Indeed JSON is not strongly typed. However, in practice, every API, every data
exchange format I've ever seen or used has used JSON in a strongly typed
fashion. i.e. they say "the returned object will have a key of 'foo' with a
number as the value, and a key of 'bar' with an array of strings as the value.

Why is this nicer?

Let's say you are working with the Reddit API. You can, of course, do it the
way you suggested, and just decode the result into an untyped object. However,
I find this incredibly brittle. You end up with strings indexing into arrays
all over the place.

On the other hand, when you decode into a Go struct, you use the regular dot
syntax to access parameters. You can't misspell these or use the value
inappropriately (trying to loop over a JSON number, for example). You can
write comments on the fields to document what you expect various values to
hold. It is nicer in the same sense that using classes is nicer than just
using arrays for everything.

Another benefit is of course the improvement of performance. Accessing an
string value in a JSON object by a key is the equivalent of a hash table
lookup in Python or PHP. It is incrementing a pointer by a constant number in
Go (assuming you use strongly typed decoding).

I'll say it again, Go's encoding/json can do what you want (the equivalent of
json_decode). There are better alternatives available to users of that
package, and the GP was discussing how to exploit one of those better
alternatives without having to write the struct by hand (which I personally
find a trivial one time cost).

~~~
lucian303
json_decode() without the second param or with it as false will create an
object for you that is typed, loosely only if you mess with it afterwards. So
what is the advantage other than speed? If I'm CPU bound, then yes, it's worth
a look just as many other alternatives are worth a look. But that is a whole
different issue.

~~~
kkowalczyk
Speed is pretty important.

Compiler telling you about a bug because you have a typo in your code (as
opposed to blowing up at runtime, sometimes in a way that you won't notice) is
also important.

Struct definition is also a documentation of your data. Another developer (or
you a month from now) doesn't have to go back and re-read, say, Redit API
docs. He (or you) can just re-read definition of the struct and know all the
data that a given JSON request provides. That's nice.

An editor can parse the struct definition and give you auto-complete, which is
also nice.

~~~
lucian303
Really? Another static vs dynamically typed language argument? Not this year.

------
chewxy
And for those of you who are not cofortable running with net/http (it is a
rather simple server), there is always uWSGI support for Go, which I found to
be a rather brilliant idea

~~~
kkowalczyk
(I wrote the article and 3 web apps on Go).

I would be much more uncomfortable running on uWSGI than on net/http. As far
as I can tell
([https://github.com/unbit/uwsgi/blob/master/plugins/go/src/uw...](https://github.com/unbit/uwsgi/blob/master/plugins/go/src/uwsgi/uwsgi.go))
Go's uWSGI implementation is just a small wrapper over C code inside a dll.

It's not portable (support for cgo on Windows is extremely sketchy).

It also goes against common sense. Any code you can write in C, you can write
in Go, except it'll be easier (Go is garbage collected, has built-in arrays,
strings, hash tables etc.) and there's drastically smaller chance Go will have
a security issues due to memory over-write.

It duplicates lots of net/http functionality.

net/http is well documented, well tested, reviewed by extremely knowledgeable
people.

Most importantly, it is being used in production by me and many other people.

Finally, net/http gave me everything I needed to write my web applications.
Before I would even considering using uWSGI (or anything else) someone would
have to explain what exactly does it provide that is so indispensable for
writing web apps.

~~~
mitchi
You have basically just described the advantages of the D language too. Do you
plan on trying D?

~~~
kkowalczyk
I did try D when it was in its early days (i.e. D 1) but at the time I was put
off by lack of documentation, the standard library split (phobos vs. D) and
general immaturity of the system. I'm sure things have improved since then but
I really like Go's simplicity.

------
Benferhat
Is 7776000 pageviews/month the kind of traffic that you'd expect to be able to
generate $80/month? $0.00001/pageview/month? If the average user viewed 1,000
pages a month, that would be $0.01/user/month.

Obviously it depends on the average pageviews per user, but what's your gut
feeling? Should $80 have been too expensive?

~~~
kkowalczyk
Your math, while precise, is meaningless.

I probably could have gotten away with paying $0 if I didn't care about the
best performance.

App Engine is distributed. You get one front-end instance for free. The more
front-end instances you spin up, the lower the latency for your requests
(consider a fron-end instance a process, the more processes you have, the more
requests you can handle in parallel, which lowers latency for each request).

All the money was spent on additional (3, I believe, front-end instances).

Was the price high? Yes, which is one reason I switched to a $60/month kimsufi
server which hosts the blog and still has 99% of capacity free for other
things.

It's possible I was over-paying. I'm not an App Engine expert. I picked the
number of instances more on a gut-basis than a comprehensive analysis basis. I
could afford it so it wasn't a big deal.

~~~
Benferhat
Ah, I thought GAE was spinning those instances up for you automatically.
That's the default, it spins up extra instances as-needed to keep latency
down. With Go apps, that's generally down to i/o from API calls.

------
eikenberry
I don't understand the deployment section. Go has the simplest deployment I've
ever had the pleasure to use. You compile the binary and copy it up. Static
binaries make it so simple as to be trivial.

~~~
kkowalczyk
First, if you use C libraries, you can't just compile on OS A and copy to OS
B. I'm not 100% sure but while Go has much better cross-compiling story than
others, I believe net/http does uses OS's C library and therefore cannot be
cross-compiled that easily.

Also, you have to copy the assets (templates and such) and if you're deploying
a new version of a web app, you don't just overwrite the binary. My script
makes sure that if something goes wrong (i.e. a new version doesn't work or
has a bug), it's easy for me to revert to previous version.

That being said, none of that implies that Go makes deployment harder (or
easier, for that matter) than deploying code in other languages would be. It's
pain in the ass but nothing that I couldn't solve in a day with a script
written with Fabric.

~~~
icebraining
_My script makes sure that if something goes wrong (i.e. a new version doesn't
work or has a bug), it's easy for me to revert to previous version._

Isn't that the point of version control? Any DVCS makes that easy to do.

~~~
Nagyman
The point is that there is an existing application in production and a new
application is being deployed. If the deployment fails, it simply does not
enable the new application, leaving the existing one running. Using version
control to rollback a running application is inadvisable (yet quite common).

------
graue
The links for securecookie and mux links are down (redirecting to
<https://www.gorillatoolkit.org/>, which doesn't respond).

~~~
BarkMore
The documentation is also available on GoDoc:

<http://godoc.org/github.com/gorilla/securecookie>
<http://godoc.org/github.com/gorilla/mux>

