
Go is boring - iand
http://aeronotix.pl/blog/go-is-boring
======
1337p337
This is largely spot-on. Of course, the author's assertion (that having all of
these things in one place is novel) is incorrect for some programmers, but the
sheer boringness of the language is a virtue. Go's features as bullet points
are unimpressive; the set of features is the impressive part. Putting in
features that are solidly understood, that are desirable, and that don't clash
with each other make for a simple, solid, nice language.

I've tried without success to dig up an email from Linus Torvalds (on the
LKML?) where, responding to an email complaining that a particular
implementation of ARM does not breaking any interesting ground, he goes on a
mini-tirade about the lack of appreciation for a simple thing done well. I
think Go fits the description nicely.

------
onan_barbarian
I reached the same conclusion ("Go is boring") myself, but with a different
flavor.

After having spent a great deal of time in recent years doing things like
GPGPU and a _whole_ lot of SIMD programming (not to mention a lot of use of
the STL, BGL, etc), I have to say I'm less impressed by the boringness (aka
taking good, solid choices from existing languages) of Go.

I understand that not everyone is excited about SIMD or generic programming or
writing code for 32768 GPGPU threads... but Go feels like a missed opportunity
in these respects, solving the problems of the mid-1990s with aplomb (which is
good).

It seems more like 'a better Java' - solid, but not genuinely breaking any new
ground in a way that creates a single good reason to use it.

~~~
genbattle
To be fair, no programming language has really taken a first-party approach to
those specific problems.

SIMD and GPGPU both fairly difficult low-level concepts as they stand: I think
there would definitely be some valuable postgrad research in looking at how to
create higher-level interfaces to graphics acceleration and GPGPU/SIMD that
are as simple and effective as Go's goroutines.

The main problem is that SIMD and GPGPU (even hardware accelerated graphics,
to a lesser extent) are bolt-ons; they're not a core part of every computer,
which is why they don't usually form a core part of any programming language.
At best languages might choose to integrate this functionality into the
standard library, but i don't think it will ever come built-in for a general-
purpose language (maybe for a domain-specific language?).

I've actually been attempting to write a GPGPU interface between Go and
OpenCL[1], so it's certainly not impossible to do GPGPU or SIMD in Go (via
cgo), but it would require writing your own 3rd-party libraries or making
additions to the go runtime/compiler to develop a novel interface to this
functionality like goroutines that can run on the GPU (a dream many people in
the Go community share).

[1] <https://bitbucket.org/genbattle/go-opencl>

~~~
tmurray
reasonable SIMD support (let's limit it to SSE2 and above for "reasonable")
has been in every Intel processor since what, Pentium 4? it's not much of a
bolt-on anymore. one of the causes of the lack of good programming models for
SIMD is that autovectorization was supposed to generate SIMD code for every
application, but autovectorization isn't actually that great for many (most?)
applications. (plus naive developers generally write terrible code--if array
of structures versus structure of arrays doesn't make sense to you, you're
probably writing code that cannot be autovectorized)

the lack of a magic compiler bullet is infinitely more true as soon as you
look at anything remotely like a GPU, which gets into other more complicated
problems due to a distinct memory space.

if I were to add any features like that to Go, I'd probably look in the
direction of generating ISPC ( <http://ispc.github.com/> ) or ISPC-like
output. no need to solve the distinct address space issue (which you cannot
solve), you have work creation so you don't need to do crazy scheduling hoops
like persistent launches on the GPU, and it performs very well on Intel
processors for SIMD-friendly applications.

~~~
pcwalton
I don't think the issue of separate address spaces is unsolvable. As long as
you have a type system powerful enough to forbid aliasing between the CPU and
the GPU code, you can do it. (For example, Rust's type system can encode task-
local data.)

------
crazygringo
Site seems to be down, here's cache:

[http://webcache.googleusercontent.com/search?q=cache:http://...](http://webcache.googleusercontent.com/search?q=cache:http://aeronotix.pl/blog/go-
is-boring)

------
hasenj
I'd like to point out that I never heard of coroutines before Go. Not even in
computer science; and I did take an Operating Systems course.

I also never seen any language doing interfaces like Go. Go does it just
right. I find that this is pretty impressive as a feature on its own.

~~~
masklinn
> I also never seen any language doing interfaces like Go.

OCaml has used structural subtyping since the beginning for its object layer.
C++'s templates also use structural subtyping on type arguments. Pierce also
covers the subject in TAPL.

> I find that this is pretty impressive as a feature on its own.

There are advantages and inconvenients to structural subtyping (compared to
nominative): it's more flexible and has much lower overhead, but it's subject
to false positives (structurally equivalent but semantically unrelated
objects) and tends to have much worse error reporting. Not to mention
structurally typed systems still usually have and need nominative types in
their core, for "non-object" types.

~~~
hasenj
I don't know what structural subtyping is, but I no that Go's interfaces are
nothing like anything in C++

~~~
dan00

        class A { public: int do() { return 1; } };
        class B { public: int do() { return 2; } };
        
        template <typename T> int do(T t) { return t.do(); }

~~~
Olreich
How does one use that template? Can you show me a function that takes anything
with a do() method? Like this?:

    
    
        do<A>(a)
        do<B>(b)
    

Can I take any arbitrary type with an "int do()" method and use that with do?
Like:

    
    
        do(Arbitrary)

~~~
dan00
"How does one use that template? Can you show me a function that takes
anything with a do() method? Like this?:"

It should work without the template parameter: do(a), do(b)

"Can I take any arbitrary type with an "int do()" method and use that with
do?"

Yes.

~~~
Olreich
cool

~~~
masklinn
As dan00 noted, it works without the template as long as there is no
ambiguity. If there's an ambiguity (a template function defined on <int, int>
and <double, double> to which you provide an int and a double) then you have
to use explicit template parameter to specify which overload will be used.

It's not the case here, so it just works.

------
trung_pham
I love static typed language. With a proper IDE, code navigation, completion
work like magic. I end up doing less typing than the dynamic typed language.

Have you ever tried to auto complete the 'init' function in RubyMine? It will
ask you which one of the 100 init functions do you mean. :)

Not with static typed language. There is only one init function to choose from
because the IDE knows the exact type you are working with at all time.

~~~
irishcoffee
I think the counter-argument here would be that dynamically-typed languages
let the person behind the keyboard run the show, as opposed to the IDE.

~~~
eru
Alas, nobody has written a really good IDE for Haskell, yet. So we still have
to run the show for that statically typed language manually.

~~~
protomyth
If I ever develop a program language, the first action I will take is the
clang approach and make it a library based architecture. That way, people can
build tools for the language including IDE integration without having to
reinvent the wheel.

~~~
tikhonj
I think GHC does something like that. At the very least, it exposes an API
that lets you do all sorts of fun things. There are projects like Scion[1]
that let you integrate that into an editor.

[1]: <https://github.com/nominolo/scion/>

However, there is simply less drive to develop tooling like that for Haskell
than there is for Java. Haskell is a much easier language to use given just a
moderately intelligent text editor and a REPL than most others. Java, on the
other hand, it verbose and annoying even _with_ a very good IDE.

So Haskell _can_ have good support, but since it isn't terribly necessary it
isn't anything like a top priority.

~~~
obtu
Indeed, “the architecture of GHC” mentions some uses of GHC as a library:
<http://www.aosabook.org/en/ghc.html>

------
ozataman
I've tried giving Go a try a bunch of times now. My primary choice of language
is Haskell and I just can't seem to get excited about Go.

~~~
thebigshane
Would you say your interest in programming languages is largely academic in
nature? I get the impression that Haskell mostly (for now at least) fits best
with academia, Java/C# for enterprise, python/ruby for smallish web apps,
Go/C/C++/Java for industrial applications (like servers, etc).

There is a very real possibility that Go is just not the right fit for you
with your current requirements. No language is the right fit for every
application.

~~~
ozataman
Not at all. In fact about 95% of all Haskell I write - and I write quite a bit
- is for commercial stuff, ranging all the way across large-ish (not quite
google-scale, yet) scale computation, distributed systems, machine learning,
modeling/simulations and web development. More academic feeling stuff like
parsing and DSLs are just the cherries on top (though even those were for
commercial uses).

I'll admit Haskell has a steep learning curve, but once you're there, all this
stuff Go is said to do real well feels fairly lackluster compared to what you
can find in Haskell-land. What's built into Go can be achieved at the library
level in Haskell. As a result, we keep seeing better and better manifestations
of key ideas in the library space.

Examples include Cloud Haskell, many, many concurrency libraries, STM,
Parallel Haskell, many constant-space data streaming libraries (pipes,
conduits, enumerators, ...), several excellent parsing libraries (parsec,
attoparsec, trifecta, ...), etc.

As a side note, I used to do lots of python/ruby - I really can't anymore.
They feel simultaneously more burdensome to code (no static type-checking),
more verbose (no elegant, long pipelines of computations), less expressive (no
_real_ first class functions - you barely use map/reduce/fold/etc. in python)
and slower (as in runtime).

Having said all that, I do see how Go fills a gap in the market. You need
something that's easy to grok and gets just enough of it right that you can
produce fast, type-safe-enough and concurrent programs with somewhat less
mutable state than what you may be used to in C. A simple mental model and
ease of entry are conceivably great for larger, homogeneous teams.

~~~
nimrody
Can you recommend any open source project that you consider a good example of
Haskell usage?

(meaning both practical and well-written)

~~~
bru
I'd say xmonad[1]! It is a very light and fast tiling WM.

There's also a couple of elegant and blazingly fast web frameworks, such as
Yesod, Snap and Happstack[2].

1: <http://xmonad.org/>

2:
[http://www.haskell.org/haskellwiki/Web/Comparison_of_Happsta...](http://www.haskell.org/haskellwiki/Web/Comparison_of_Happstack,_Snap_and_Yesod)
[http://stackoverflow.com/questions/5645168/comparing-
haskell...](http://stackoverflow.com/questions/5645168/comparing-haskells-
snap-and-yesod-web-frameworks)

~~~
slurgfest
Installing xmonad requires several hundred megs of dependencies, so what does
it mean for it to be light? Low memory footprint?

~~~
antihero
Pretty much. Hard disk space is still cheaper than RAM, so I think it's a good
tradeoff. Plus those dependencies can be used for lots of other things.

------
StavrosK
As a long-time Python programmer, I tried Go recently for something that
needed large amounts of concurrency (a hosted version of hubot:
<http://instabot.stochastictechnologies.com>), and I have to say, I am very
pleasantly surprised.

The type system was a bit cumbersome, after coming from Python, especially
having to wrangle with pointers after not using them ever, but it's nothing
you don't get used to. I'm still not sure how much I gain from static typing,
but I'm willing to bear it out.

Channels and goroutines, however, were an absolute dream to use. The entire
IRC frontend runs off one process, which, I am led to believe, will basically
never need anything more (it just proxies messages from IRC to the backend and
back). Communication with the processes was fantastically easy, creating,
launching and reasoning about goroutines is, again, very straightforward, and
all this feel very much like a first-class citizens.

Python has gevent too, and it suited me very well, but Go feels more
integrated and better done.

~~~
slurgfest
I think what you gain from static typing is pretty much that you can compile
your programs and run without a fat interpreter.

Note - I am not saying that is the only possible benefit of static typing
anywhere, e.g. in Haskell - this is more in line with C, you are doing type
declarations to cue the compiler rather than to realize some utopian test-free
development methodology.

~~~
StavrosK
Oh, definitely, I'm just not sure it gains that much speed compared to Python.
I'd expect Go's speed to be on par with C, but, from what I understand, it's
more like PyPy.

Of course, this is just from what I hear, I haven't run any benchmarks. Does
anyone have more details about this?

------
rsaarelm
Having simple, established ways for doing most common things makes it easy to
write code without thinking about decisions around the programming language,
such as how the syntax should be formatted, how the symbols should be named,
how should memory management be arranged, what conventions should be used for
splitting code into files and modules (with little extra design issues
involved in structuring header files and include relations, in case you're
doing C/C++), what kind of build system should be used, which unit test
framework should be chosen and which third party libraries should be chosen
for the very commonly needed stuff that's nevertheless not included in the
language's standard library since it was standardized somewhere in the late
80s.

Having all this stuff basically solved out of the box makes it very easy to
start cranking out actual solutions with Go, even though none of that is
particularly interesting from a programming language design standpoint.

------
lazyjones
The author makes valid points and some of the reasons why I tested Go recently
are named, but when it was ~15x slower than Perl and 10x slower than Java on
some simple regexp matching, I gave up on it.

~~~
dhconnelly
There's some history behind this. You can read some of it from Russ Cox, one
of the Go authors.

[https://groups.google.com/forum/?fromgroups#!topic/golang-
nu...](https://groups.google.com/forum/?fromgroups#!topic/golang-
nuts/6d1maef4jQ8) <http://swtch.com/~rsc/regexp/regexp1.html>

Edit: missed another good one. There's a lot of discussion about this on the
mailing list. [https://groups.google.com/forum/?fromgroups#!topic/golang-
nu...](https://groups.google.com/forum/?fromgroups#!topic/golang-
nuts/GNLTUTFNNl0)

------
charlieflowers
The thing that makes me pull back from trying Go is the fact that it has no
exceptions and no other feature for handling errors (correct me if I'm wrong).

Ugh! I can't imagine going back to the days when I had to call a function,
check its return value to see whether there was an error or not, then, if no
error, proceed to the next function call, check it for error, and so on.

I know exceptions were a source of "complexity", and you could say that Maybe
monads or other programming attempts to solve the problem increase complexity
too.

But to just punt and go back to doing it the ugly, unmaintainable brute force
way? I just find that hard to swallow.

------
ak217
This sounds really interesting and compelling.

As someone new to Go... What would be the advantages of using Go over Python
(taking into account the emergence and future ascendancy of pypy)?

~~~
dhconnelly
A few:

\- Go has language-level support, in the form of goroutines, for multithreaded
concurrency. Python is single-OS-thread-only, and PyPy doesn't change that.

\- Go has enough static typing to help you write safer code, without the
verbosity of "bigger" languages like C++ or Java. If you write a lot of tests
for your Python app, you might not have variable typos or function argument
type mismatches, but in Go the compiler catches these things.

\- Go is compiled to machine code. This means that, barring a miracle in
JIT/VM research, Go will probably always be faster than PyPy for most tasks.

These, together with the fact that many of the niceties of Python are
available in Go (lightweight syntax, first-class functions, iterators and list
slicing, etc), make it, in my opinion, a compelling alternative to Python.

~~~
irahul
> Python is single-OS-thread-only, and PyPy doesn't change that.

Python uses native multi-threads, but the GIL restriction means only one
thread can run at a time regardless of number of cores or processors you have.

> If you write a lot of tests for your Python app, you might not have variable
> typos or function argument type mismatches, but in Go the compiler catches
> these things.

Use pylint and/or syntastic(for vim).

> Go is compiled to machine code. This means that, barring a miracle in JIT/VM
> research, Go will probably always be faster than PyPy for most tasks.

Go is slower than Java.

[http://shootout.alioth.debian.org/u32/benchmark.php?test=all...](http://shootout.alioth.debian.org/u32/benchmark.php?test=all&lang=go&lang2=java)

They removed lua-jit from the benchmarks. lua-jit will smoke go in most
scenarios. Here is a comparison between lua-jit and lua.

<http://luajit.org/performance_x86.html>

Native code doesn't mean "always faster than JIT/VM". A good JIT can do
optimizations which a static compiler can't. For a long running process with
hotspots(same code hit multiple times), a JIT can be as good as(or better)
than native code.

~~~
irahul
For some reason, masklinn's comment is dead. Posting it here:

<quote>

> Python uses native multi-threads, but the GIL restriction means only one
> thread can run >> Can run Python code, if you're multithreading for e.g. IO
> the IO code will generally release the GIL.

</quote>

Yes, native code can release the GIL and run in parallel. As far as it's pure
python, only one thread runs at a time. The options are multiprocessing,
gevent style concurrency(which I prefer to node's) and native extensions. It
isn't as bleak as people make it out to be.

~~~
masklinn
> For some reason, masklinn's comment is dead. Posting it here:

Sorry, that's probably because I got error messages while posting ending up
with 2 or 3 comments, and I removed the extraneous ones. You probably tried to
reply to one of those I deleted.

------
olaf
I think the purpose of Go is to solve some of Googles very specific problems
(e.g. easiness feeling comparable to Python, short compile teams, ease
construction of concurrent internet server apps), not to enthuse anybody. If I
see it as an unspectacular, better Python, not as a top modern language then
it makes some sense to me. It seems they had to sacrifice sth. for short
compile times (e.g. generics).

------
soofaloofa
Boring != bad.

~~~
mathgladiator
Boring also probably means "I can build an enterprise level business on it"

------
api
C is boring too, in all the right ways. I think Go could be what we've been
waiting for: C 2.0.

~~~
ntrel
C's preprocessor means C code can often do interesting tricks, such as the X
macro: <http://www.drdobbs.com/the-new-c-x-macros/184401387>

There are tons of other interesting uses for macros. Obviously I'd rather a
language had safer equivalents to a C preprocessor.

------
Ziomislaw
I view 'boring' as an advantage. Go is so 'boring' that you just can't focus
on the language, you focus on your task.

------
KlausTrainer
Maybe the website wouldn't be down right now if it'd run on Go.

------
D_Guidi
link broken :(

