
Swift and Go: Building a Fast Future - rohamg
http://axioms.io/zen/2014-11-06-swift-go/
======
Roboprog
As much as I dislike that most of the "language shootout" benchmarks are
mostly numeric wanking, the binary tree benchmark actually makes, uses and
disposes of quite a few data structures, and seems more like a real
application program to me.

Go isn't yet faster than Java, but it is closing the gap, at least on multi-
core:
[http://benchmarksgame.alioth.debian.org/u32q/benchmark.php?t...](http://benchmarksgame.alioth.debian.org/u32q/benchmark.php?test=binarytrees&lang=all&data=u32q)

Single core doesn't fare so well (Go vs Java), though:
[http://benchmarksgame.alioth.debian.org/u32/benchmark.php?te...](http://benchmarksgame.alioth.debian.org/u32/benchmark.php?test=binarytrees&lang=all&data=u32)

Perhaps the authors should have used Rust, or Ada, rather than Go? Hell, on a
single CPU machine, FreePascal seems to do better than Go :-)

Actually, from a "performance, w/out turning off all the safeties" standpoint,
it really looks like Rust is owning that space.

Now I gotta learn Rust... :-)

~~~
melling
Rust looks great but hasn't shipped yet. Go is production quality and it's
being used in some large projects at Google and elsewhere.

[http://blog.golang.org/4years](http://blog.golang.org/4years) \- From Nov
2013

No, the Go optimizing isn't great. This will be addressed after the compiler
is completely rewritten from C to Go. The Go community is growing too, which
is probably more important than how well you do on a micro benchmark.

~~~
cromwellian
I don't understand how writing the Go compiler from scratch in Go is going to
make it better than super-mature compilers. Wouldn't it better to leverage
Clang/LLVM? Redoing all the optimizations by rewriting the whole compiler in
Go seems like it will significantly delay performance parity.

~~~
riwsky
For what it's worth, the go team's plan is to automatically translate the
compiler to go, not to rewrite it from scratch:

[http://talks.golang.org/2014/c2go.slide#18](http://talks.golang.org/2014/c2go.slide#18)

And, the gccgo compiler does leverage gcc, assuming that counts as a mature
compiler:

[http://blog.golang.org/gccgo-in-gcc-471](http://blog.golang.org/gccgo-in-
gcc-471)

. Neither of these contradict your implicit point of "they chose to invest
time in this port instead of trying to maximize performance ASAP", but you
still might want to know.

~~~
cromwellian
Seems weird to fork a compiler like gcc or clang via transpilation, because
you split the community. It may be faster to iterate on Go, but will all of
the compiler contributors on GCC or Clang/LLVM want to switch to editing the
go version?

It seems you'd lose out on picking up improvements from the main compiler
branch and have to keep transpiling and gardening in patches. Plus upstreaming
improvements would also be irritating.

I'd think a Go frontend to LLVM would be optimal in terms of productivity.

~~~
e12e
The go compiler is based on the plan9 c compiler, not gcc. I'm not quite sure
what the story is with gccgo (who initiated it, why) - but i think it was for
interfacing with c on non-plan9 architectures, and not really about leveraging
gcc optimizations.

~~~
astrange
gccgo was written by a gcc developer for the purpose of trying out new ways to
write a frontend, but also to use all the various things gcc has.

[https://blog.golang.org/gccgo-in-gcc-471](https://blog.golang.org/gccgo-in-
gcc-471)

The Go developers have claimed LLVM was not useful because it's too slow,
which is why they used the plan9 compiler style.

------
bsaul
Just trying go for some real project, and frankly i wouldn't use it for
anything else but network-related middleware ( or low level services), which
is what i'm using it for, and almost every tutorial i've read about this
language mentions.

As long as you're building something very technical, everything's fine. But
once you go out of this path, you can see the walls getting dangerously
closer. For example, i was surprised to see how many runtime errors i got
while coding, for a statically typed language. Surprised as well to see that
error checking made me wish for a goto statement again ( what's the pattern
for handlings all errors in a block with the same code ? Please tell me..)
Then i started to code against a sql db, and boy did it bring me old memories
back. Manual transaction scope handling ( annotation where are thou ?),
manually counting bound variables in a statement, finding mismatched types
between nullable ones and regular ones.... What a mess...

Now it _may_ only be a matter of waiting for advanced librairies to mature,
but somehow i doubt it.

~~~
howeman
Go does have a goto statement, and one of its good uses is to transfer to an
error handling block (from what I've seen).

There are also type annotations (tags), though I don't know how/if they relate
to sql

------
twic
> I'm pretty darned sure that Rob Pike (creator of Go) and Chris Lattner
> (creator of Swift) know a few things about computer languages that the rest
> of us haven't sussed out yet. If these guys think the world needs a new
> language, it's worth finding out why. (And if you do know more about
> programming languages than these two? Well, it's honor to have you reading
> my article, Mr. Wall!)

Larry Wall is the _ne plus ultra_ of programming language design. This is
satire, right? Please tell me this is satire.

~~~
pdabbadabba
Is that not the point of his remark? As I understand him, he's implying that
Larry Wall is the only one who knows more about language design than Rob Pike
and Chris Lattner. Therefore, we should listen to Rob and Chris.

Or maybe it's your comment I'm misunderstanding?

Edit: Ah. It's been pointed out that perhaps your own remark about Larry Wall
was intended as sarcasm (or, equivalently, was intended as a paraphrasing of
the quote above it). So it's probably the latter.

~~~
dminor
He's disagreeing about Larry Wall.

------
coldtea
> _By now, you may be asking yourself why we would choose to use such nascent
> languages in a production environment._

No, we realy are not. If anything, both are quite safe bets.

Swift had been in secret development for years and came out almost fully
formed (as far as languages go), with a full API, tooling, documentation, etc.
Besides it's the Apple blessed way to do things on iOS going forward.

As for Go, everybody and its dog are using it for production, left and right.
Including very big names. It's pretty much a given that the language is
already production-proven, and will do well in the future.

~~~
rgovind
>>Full API, tooling, documentation, etc. Besides it's the Apple blessed way to
do things on iOS going forward.

Full API? I believe apart from xcode, there are no developer tools or no
examples of parser API. Am I missing something?

~~~
coldtea
By "full API" I mean the Cocoa libraries it ties to, not some API for messing
with the language (AST stuff etc).

As for developer tools, they have an IDE, a compiler, a debugger, a UI
designer, the "code playground" thing, etc. That most of those are (also)
embedded in XCode doesn't change much.

------
Joky
Yes! Two modern languages that are 1) statically typed and 2) statically
compiled. At least some people still get it that "modern" and "nice to use"
does not implies scripting-like dynamically-fancy typed language "à la"
PHP/Python/Javascript/... And the author did not mention Playground for Swift
which is just incredibly useful to start experimenting with the language!
(Edit: of course Rust is another one as well, but I was in the context of the
article)

~~~
derengel
you know what they say about Go being modern right?

~~~
Joky
please, enlighten me :)

~~~
jakevn
For better or worse, Go's design is anything but modern.

It lacks things such as immutability and generics. It also perpetuates the
mistake of including a run-time type error, null (nil).

~~~
Joky
Note that modern does not mean perfect. I'm not sure you answer could not fall
into the "this-language-lacks-my-favorite-cool-fancy-feature-so-it-is-
necessarily-an-old-fashioned-crappy-piece-of-s*" syndrome?

~~~
jakevn
Were they actually fancy or cool, maybe. They're rather basic features among
statically typed languages.

Also, I'm not trying to say Go is bad or that I dislike it. It's simply not a
modern language as far as design goes.

------
gnufied
I have been playing a lot with QML lately and I am loving what I see there.
Their approach of animations or graphics seems simple and very approachable -
[http://qmlbook.org/ch05/index.html](http://qmlbook.org/ch05/index.html) .

The reason I bring this up is, while I like swift (and own more than one
macbook pro), I can't bring myself to code for a platform which ties myself
further with Apple eco system.

If you are looking to build a cross platform 2D game for Android/iOS/OSX/Linux
- QML seems like a very good choice.

------
nathan_f77
Hi @rohamg, I was wondering if you could please share the libraries and
frameworks you are using? I'm also building a mobile app in Swift with a web
backend in Go. I've done a bit of research, and I think I'm going to use the
following:

iOS:

* MagicalRecord - CoreData abstraction ([https://github.com/magicalpanda/MagicalRecord](https://github.com/magicalpanda/MagicalRecord)) * mogenerator - better CoreData class management ([https://github.com/rentzsch/mogenerator](https://github.com/rentzsch/mogenerator)) * RestKit - with REST API endpoint ([http://restkit.org/](http://restkit.org/))

Go:

* Gin - Web framework. I really like the focus on performance, and that it seems to include all the features you need for an API (authorization, route grouping, etc.) ([https://gin-gonic.github.io/gin/](https://gin-gonic.github.io/gin/)) * gorm - for most CRUD operations / queries ([https://github.com/jinzhu/gorm](https://github.com/jinzhu/gorm)) * sqlx - for more complex queries ([https://github.com/jmoiron/sqlx](https://github.com/jmoiron/sqlx)) * apns - push notifications ([https://github.com/anachronistic/apns](https://github.com/anachronistic/apns)) * gingorelic - New Relic integration ([https://github.com/q1t/gingorelic](https://github.com/q1t/gingorelic)) * APIBlueprint - API documentation ([http://apiblueprint.org/](http://apiblueprint.org/))

~~~
nathan_f77
Argh, formatting. And now I can't edit or delete it.

------
notduncansmith
How does a language without generics claim to "do more with less code"? Don't
get me wrong, I like Go, but it's hard to get behind any language with that
low of an abstraction ceiling. Then again, I work in a web shop, building CRUD
apps for a living, so maybe it doesn't matter for people who only have to
build one version of something.

~~~
Roboprog
We survived getting things into and out of Lists in Java 1.2 to 1.4 somehow.
The typecasting on the .get(...) calls is a nuisance, but a minor one.

~~~
pjmlp
Back in 2002. 12 years ago!

~~~
Roboprog
It was a dark age, and void stars filled the console. Many a core were dumped.
An age where boys became men!

:-)

------
yvsong
Which database do you Go for? Is the driver production ready?

~~~
chris0987
We are using [https://github.com/go-pg/pg](https://github.com/go-pg/pg) for
Postgres with some luck, but I think the standard is
[https://github.com/lib/pq](https://github.com/lib/pq). We are also developing
a driver for Orient DB with the goal of it being production ready.

------
Dewie
> Go compiles very quickly, but that actually didn't impact us very much since
> we have largely been using interpreted languages on the backend. I'll betcha
> those poor Java programmers get pretty excited about this, though!

Oh?

~~~
twic
Someone should probably mention to the author that us poor Java programmers
have had incremental compilers for over a decade, so compilation speed hasn't
been an issue for a long time.

Best not to mention that we've also had generics for over a decade, though,
wouldn't want to upset him.

~~~
dete
Well, you can consider it mentioned to the author... that would be me!

I shouldn't have tweaked Java so mercilessly since I did love the language for
so long (lo, these many years ago). However, I do think you really
underestimate the compile speed of Go. Even if 99% of your builds are
incremental, you can't entirely discount the occasional clean build. While it
has been many years since I hacked Java, even incremental builds could take
more than a few seconds. Even a clean build on our 50 kloc Go codebase clocks
in under 2 seconds (0.1s when the disk caches are pre-warmed).

As for generics, I do like them, and seeing them on iOS (with Swift) is a
pretty big win. I'm not entirely convinced that Go is much poorer without
them, however. The type system in Go is really unique; if you tried to program
Go using Java-style paradigms, there's no question that you'd find it pretty
disappointing. However, Go does allow some new ways of thinking about types
that allow a degree of flexibility that simply can't be expressed with formal
class hierarchies.

If what you're doing works for you, just keep on truckin'. But if you give
some of these new languages a chance, you might find the areas where they
really shine. We did!

~~~
lobster_johnson
If you want to contrast compile speeds, try Go vs. C++. Java compilation has
been very fast for a long time, as others point out.

For my part, my main beef with Go isn't necessarily the lack of generics, but
the obstinate lack of expressiveness. It's back to Java or Python where you're
forced to break up your code into discrete, imperative chunks instead of
chaining stuff together in elegant flows. It's like Go's authors missed out on
functional programming. No pattern maching, which seems like a huge miss
considering Go has select { }. Go's syntax is, in many ways, even more rigid
than both Java and Python.

That rigidity extends to error handling. While I agree with the _philosophy_
behind Go's rejection of exceptions, I don't agree with how it's been
implemented. In discussions about Go people always talk about exceptions vs.
explicit error returns, but hardly anyone mentions the fact that error
handling completely takes over our code: errs are everywhere!

A concrete example: Go has := for type inference, but it turns out you can
almost never use it, because almost every function needs an "err" that you end
up declaring. Often you start out like this:

    
    
        if result, err := getResults(); err != nil {
          return
        }
    

Quite elegant. But then you need to add some more code, and you actually can't
rely on type inference anymore:

    
    
        var err error
        var result *Result
        if result, err = getResults(); err != nil {
          return
        }
        stats, err = computeStats(result)
    

It turns out that just because you needed another "err", you had to rewrite
the statement, which is frankly ridiculous.

The next problem here is that we can't simply this:

    
    
        result, err := computeStats(getResults())
    

That's because computeStats() takes a _Result, not two arguments (Result_ ,
error). In functional languages, this is elegantly solved through monads, but
not in Go; you can't "short circuit" function chains that might return errors.
There goes your expressiveness.

Another problem that the error phenomenon infects the language with is that
you can't have global variables initialized this way:

    
    
        var spaces := regexp.Compile(`^foo`)
    

To get around this, the regexp module defines an alternative function:

    
    
        var spaces := regexp.MustCompile(`^foo`)
    

(Never mind the fact that you're not allowed to declare this as a const. It
_is_ a constant, I want it to be a constant, not a global variable!)

The fact that almost _every_ function ends up having an "err" around raises
the question: Why is it not an integral part of the language in the first
place? Why do _I_ have to declare err?

Other languages (Swift among them) fix this problem through sum types: The
function can return a value which is _either_ a real value or an error. Go's
idea of returning a value _and_ an error is logically nonsensical in almost
every case, because the error is used to signify that the value isn't
available due to failure. I'm not a language-theory purist who thinks everyone
should really be using Haskell; these are _practical_ concerns.

Overall, Go does feels disturbingly warty in places, which is incredible for a
new, clean-slate language. Favourite wart: interface types being magically
pointer-based, leading to the whole non-nil value being nil idiocy; it's
mindblowing that they got this so wrong.

I liked Go a lot better before I started using it.

~~~
joelgwebber
My personal experience at a startup with a large amount of Go code running its
frontend and backend servers. YMMV.

First off, I also find the interface-nil thing to be a frustrating edge-case.
I also know that this design was the result of some difficult tradeoffs, as
such things often are. We can argue about whether they made the _right_
tradeoff, but I don't think it's fair to refer to it as a "mindblowingly wrong
idiocy".

Second, on error handling. Having now written a large amount of server code in
Go, I find that I strongly support their approach, even when I find it a bit
verbose. Here's how I find it actually plays out in practice:

    
    
        // You write something like this:
        result, err := getResults()
        if err != nil {
          return err
        }
    
        // Then you reuse err for the next call
        result, err := getResults()
        if err != nil {
          return err
        }
    
        stats, err := computeStats(result)
        if err != nil {
          return err
        }
    

Eventually, you realize that `return err` just isn't enough most of the time,
because it's impossible to make sense out of your logs. So we added a simple
"error chaining" function that allows you to pass context when you return the
error, which makes the logs much clearer than just a single error message, or
raw stack trace. And of course it is often the case that you want to do more
logging in your error blocks, even as you ignore the error and move on (e.g.,
"spurious error reading memcache entry; falling back to the slow thing").

The practical reality of writing good server code is that exceptions which get
caught way up the stack are inscrutable in your logs (at least that was our
experience), so it makes sense to know up-front exactly where failures can
happen, and to be forced to think about them the first time you write your
code. Yes, it can be a bit verbose, but we've found the tradeoff to be net
positive.

~~~
lobster_johnson
For the record, I don't think the interface problem is "mindblowingly wrong
idiocy" (you words!).

But I think it's a good indicator of how parts of Go's design are flawed from
the outset. Design is hard to change later, so it's important to get it right
from the start.

Again, I totally buy explicit error propagation. I just think Go's solution
ends up cluttering your code. It's so focused on errors, yet handling isn't a
first-class construct, and the mechanisms it gives you for dealing with errors
aren't very good. You have the cast check (a, ok := ...) and you can do a type
switch (switch a := err.(type) { ... }), but it's rather weak for something
that permeates every corner of the language. At least us have pattern
matching.

I find the stack frame problem disappointing. It's amazing that there are now
several libraries to create artificial stack frames (eg.,
[https://github.com/facebookgo/stack](https://github.com/facebookgo/stack))
just so you get this.

~~~
joelgwebber
I don't want to pick nits too much here, but "[...] leading to the whole non-
nil value being nil idiocy; it's mindblowing that they got this so wrong." So
I paraphrased a bit :)

I understand that some may find the error handling a bit too verbose, but
humbly submit that there's a legitimate tradeoff to be made in terms of
language complexity vs. verbosity, and the Go team generally tends to fall on
the side of simplicity over tersity. This works well for us, but not everyone
will find it palatable. YMMV and all that.

The stack frame "problem" doesn't seem all that bad to me. It would be nice to
have a built-in solution, but our own code for dealing with this is one tiny
file someone banged out in a couple of hours, so I'd hardly call it more than
a stumbling block. After watching the Java world deal indefinitely with untold
design flaws in core libraries, I support keeping things simple at the outset
wherever possible.

But hey, there are lots of choices out there, so I'm not telling anyone they
must write their servers in Go. Just that it works well for us.

