
Go Is a Shop-built Jig (2014) - amzans
http://robnapier.net/go-is-a-shop-built-jig
======
tptacek
I've always felt this is one of the better characterizations of Go. Great
programming tool. Not an especially great programming language. A lot of the
time, more than we acknowledge in PL slapfights, that's what you really want.
And, sometimes, being in an efficient but limited language allows you to focus
better on your problem domain, which can be useful creatively.

~~~
gok
On Go-the-language, I agree. It takes a few things from PL design that have
widely been shown to be helpful and packages them up in a simple language that
C/Java programmers can use to be productive in an hour or so.

The implementation is a different story. It was really goofy to implement a
new compiler backend, garbage collector, scheduler, calling conventions, and
hey, why not make have the standard library make syscalls directly, what could
possibly go wrong? The result has been the last several years has largely been
spent reimplementing solved problems (basic compiler optimizations, a GC which
is competitive with JVMs from 15 years ago, etc) rather than actually evolving
the language.

In short, I wish they'd stuck with their "just do a few things well"
philosophy in both language design _and_ implementation.

~~~
p_l
The compiler backend, till the Go rewrite, had been in production use for ~15
years or so from the top of my head, it's just neither GCC, nor the new
hotness LLVM.

Calling convention TBQH is something that often has to be custom in a language
outside of interop bits, otherwise you are forced to deal with various C-style
brammage. Unfortunately most OSes don't have language-independent interop
calling conventions (Windows has COM, VMS has, iirc, SDL, the rest pretty much
has nothing), so even if technically there's some official document
practically you get stuck with peculiarities of a specific compiler and its
relationship with C standard library. Syscalls are about the only _safe_
interface on most unices and the reason why you can make self-standing Go
programs that don't bring glibc garbage and random and unexpected shared
library dependencies, something that is quite a reason for the following Go
gets on container based platforms.

------
krylon
I cannot really put my finger on it, but Go is basically perfectly compatible
with the way my brain works. Its semantics so far have not surprised me, and I
only have to look up the language specification very, very rarely. Most of the
time (like 90+ %), I can just let my intuition guide me. Of course, Go has its
share of problems, but that one huge advantage dwarfs those problems entirely.

~~~
marcus_holmes
That, plus the lack of magic.

I can always understand what a Go program is doing because of the simple
semantics and lack of magic. It's an underrated benefit to be able to browse
the source code of a dependency and grok it easily, first time.

------
nine_k
> _I would rather spend my time writing generic, elegant functions that help
> developers_ think deeply and correctly _about their programs. Like Alex,
> falling back on for-loops and mutable state makes me feel like a bad
> programmer. But there is a certain tension between all that and_ shipping
> things today.

(Emph. mine)

It hits the nail on the head: there's a certain tension between speed and
correctness. For some, there's never enough time to do the right thing, but
always (inevitably) enough time to keep fixing a wrong thing.

There are also diminishing returns of typing imperative code fast top to
bottom, but having to deal with constant boilerplate and manually checking
things that a machine could check, were the language more expressive.

Somebody called Go "systems PHP"; I think it's very fitting.

~~~
jrs95
Ehhh I dunno about the PHP thing. I can see what you mean, but there’s a
certain negative implication to it which isn’t accurate. PHP is bad because
it’s inconsistent and doesn’t really have a coherent design. You can tell that
it evolves by having things bolted on to it, and there’s all sorts of weird
dark corners. Go really isn’t like that at all.

~~~
no_wizard
I disagree that PHP does not have a consistent design. Since PHP 7 they have
been intentionally removing all old PHP warts and pushing the language to real
consistency. They even have an RFC process now for proposing new features from
the community so they can be more responsive.

It’s not statically typed like Go but it’s far from inconsistent IMO

~~~
omnimus
I do PHP a lot and it is extremely inconsistent. Even PHP7. Like half of
standard library uses _ and other half does without them (var_dump(),
phpinfo(), gettype(), get_class()). Half uses to other half 2 (deg2rad(),
strtotime()). So many bugs because of comparsion and operators doing wierd
stuff.

PHP is mad. I think they have to keep it for legacy reasons.

Don't get me wrong i think the way php handles requests is useful for the
small websites i create and i would probably not use any other language for
that. But PHP is THE dirtiest most inconsistent language that people actually
use.

~~~
no_wizard
Perhaps I have a little bit of a knee jerk reaction. I've gotten a new job
where I have to do php development pretty heavy, and I haven't done it since I
was 19 when I was interning at my first programming job and I absolutely hated
it. Back then php 5.5 I think was the latest version and it just felt
incredibly impossible to get anywhere with it. It wasn't long after that I
moved to Python. I only recently got a different job all these years later
where I am doing it again but PHP 7 is just so much better. 7.2 in particular
even though its a point release has even done a lot to improve it.

So I feel like there is this level of people who look at people who have to do
PHP and actually enjoy it (and I have to say I am enjoying it, warts and all.
Drupal is OK but where it really shines is
[https://laravel.com](https://laravel.com) ) like we aren't 'real' programmers
unless we somehow know its a terrible language and are only doing it because
we have to.

I really like it.

With that said, if I'm being completely honest here, there are parts of the
PHP community that just down right drive me nuts. There are a lot of scammy
companies out there trying to sell PHP solutions that are such garbage. Its
like JavaScript. PHP does have a low barrier to entry (but a high bar to being
good at wielding it, much like JS. You could probably make this argument for a
lot of web tech in general) that all kinds of people use it and really feels
like it sullies the language quite a bit and some of the community around it.

Alas however, much like everyone hating jQuery without ever actually
explaining themselves or what is the technical aspects of jQuery that make it
so undesirable, PHP occupies the same space: everyone loves to hate it, it
seems.

------
closeparen
I’ve written production code in Go professionally every day for two years.
None of the language design complaints in these thinkpieces are a real
problem. You learn the idioms and it works out.

Go’s showstopper problem is dependency management. Fighting with Glide costs
at least 30% of my time and every moment of it is excruciating. My
organization started migrating to Dep just as Google announced its decision to
have the Go community continue thrashing around on the issue even longer.

My advice: do not even begin to engage with the details of the langauge.
That’s a waste of time. Understand that dependency management is horrifically
broken and that Google considers it reasonable to thrash between experimental
half-baked solutions forever. However much you may hate Java, Maven terminates
with a correct output in less than an hour, which is more than I can say for
anything in the Go ecosystem.

------
Animats
The error handling in Go seems verbose:

    
    
        if err = logit(FrobulatingMessage); err != nil {
          return err
        }
    
        if err = f.cleanupOldest(); err != nil {
          return err
        }
    

There's an advantage, though. You can easily insert code for an error case.
You might add, if cleanupOldest fails, something like

    
    
        logError("cleanupOldest failed unexpectedly while cleaning up chain")
    

if that's an unlikely but possible event that needs to be investigated. Big
operational shops do that. It's hard to stick debug code in the middle of an
expression.

~~~
TheDong
The equivalent in rust, for a fair comparison:

Before:

    
    
        frobulate(message)?;
    

After:

    
    
        frobulate(message).map_err(|e| {
          error!("error happened: {}", e);
          e
        })?;
        // or, more like the go one
        if let Err(e) = frobulate(message) {
           error!("error: {}", e);
           return Err(e);
        }
    

It's really not that different in the debug case than go, but the normal case
is less painful to deal with.

------
JepZ
I love Go, I really do. But there are some issues that should be fixed (maybe
in 2.0).

I'm not so sure if we really need full-scale generics like in Java or Rust,
but the interface system (which is the Go solution for the Generics use-cases)
certainly needs some improvements. For example, when you write a container lib
which expects an empty interface as input you constantly have to cast the type
while using the lib. The result is code which looks awful when you use the
container and horrible when you look at the container implementation.

Next, using slices of interfaces is just another bad joke [1]. there might be
technical reasons for the current state, but I am sure there are ways to solve
those issues.

One thing I am not quite sure about the way Go handles bindings methods to
interfaces. Currently, that is not supported and the practical way to do it
anyway is to embed the interface into a struct and bind the methods to that
struct, but that feels more like a hack than anything else.

Another thing that keeps bugging me is the requirement for map keys to be
comparable while that is just some internal property which some types have and
others don't. For example, functions are not comparable and therefore you
can't use them as map keys. Finding out about such stuff really sucks when
functions are considered first-class citizens.

That said, I have to add that I enjoy a lot of the positive sides of Go and
while I wish those issue will be fixed someday, I will gladly continue to use
it even with those issues.

[1]:
[https://github.com/golang/go/wiki/InterfaceSlice](https://github.com/golang/go/wiki/InterfaceSlice)

~~~
dullgiulio
I don't understand: what do you mean with binding methods to interfaces?

Interfaces just represent a bunch of functions that an object must provide
(and you can call when you "mask" the object behind the interface).

~~~
JepZ
Well, normally you bind functions to types like:

    
    
      func (m myType) calcRandom() int {
        return m.nine
      }
    

But there are some situations when it would be useful to be able also bind
functions to interfaces (e.g. some of them are similar to use-cases for
abstract classes in OOP):

    
    
      func (i myInterface) calcRandom() int {
        return i.Nine()
      }
    

While I would consider it a clean language design to be able to do that too,
it brings some additional complexity and as we know Golang doesn't like
complexity.

As I said, I am not completely sure of the consequences such a change would
bring with it and if it would enable bad practices. So I would not push too
hard for that one, but some of the other issues I mentioned are issues of
which I am pretty sure that they should be fixed.

~~~
marcus_holmes
um.. I think you've confused the interface and the implementation.

Interfaces are not the same thing as classes, and bringing anything from OOP
to them will almost certainly result in Bad Things.

------
venning
This article contains a dead link in the third paragraph marked as "bugs the
lead language designer". Here is an archive.org link from the same time
period:
[https://web.archive.org/web/20140822173033/http://gophercon....](https://web.archive.org/web/20140822173033/http://gophercon.sourcegraph.com/post/83845316771/panel-
discussion-with-go-team-members)

------
akhilcacharya
> When writing the Swift function, I found myself spending a lot of time
> thinking about how to write it. Should I use >>== or .flatMap()? Should I
> use my custom Result here at all, or should I stick to standard Swift and
> return NSError?, or maybe Bool with an NSErrorPtr? This was my first time
> using Result<Void>, and I started asking myself if I should create a
> typealias for that and maybe a helper function for the slightly strange
> looking success(()). The var bothered me. It always feels like a hack in FP,
> like you’re not smart enough to do it right. I wrote a different version
> that didn’t have a var. That duplicated self.cleanup in two places. So I
> started working on a new function that would let me include the conditional
> in the functional composition. I made and re-made a lot of choices.

This has basically been the entirety of my experience with Scala. Having too
many options - including just writing Java without semicolons - is ultimately
not great for my own productivity.

------
solidsnack9000
_So again, in the end, Go turned out to be a language for solving real
problems rather than a language filled with beautiful tools, and so you build
real solutions rather than finding excuses to use your beautiful tools. Don’t
try to make Go what it isn’t. If you’re trying to solve abstract CS problems
in their most generalized forms, then you may find it frustrating. But if
you’re trying to solve specific, practical problems in the forms professional
developers typically encounter, Go is quite nice._

This is a straw man argument. How many people who complain about Go -- or
evaluate it for a project, drop it and move on -- start out solving non-real
problems?

------
mindslight
Though to continue with the analogy, you don't want your entire workshop to
consist of ad-hoc tools that kinda-sorta work for narrow purposes. You want
your basics to be solid, well-designed, and applicable generally - so that
you're not already having to account for their individual exceptions and
shortcomings when you layer your hacky jigs on top.

I feel like there's a physical workshop analog of how (Lisp) macros get you
_one and only one_ additional layer of abstraction. I've made an impromptu
"table saw" by fastening an upside-down circular saw to a piece of plywood,
but it certainly wasn't a basis for doing anything greater and I had to be
real deliberate about plugging that thing in.

------
wejick
This is exactly what I feel when using Go. Love the way I can really focus on
solving real problem rather than trivial (but important things like styling
and formatting). About generic, when I thought need it, I always able to find
simpler design using composition.

~~~
coldtea
> _About generic, when I thought need it, I always able to find simpler design
> using composition._

How exactly would composition help you e.g. make a general purpose reusable
math library for different kinds of numeric types?

~~~
jitl
I think the implicit argument is that “a general purpose reusable math library
for different kinds of numeric types” _is not_ a real problem.

A real problem is, “I need to draw this triangle”, and using math.Cos w/
float64s works just fine.

~~~
coldtea
And yet it's a problem anybody who makes any kind of library that should work
with > 1 types, faces...

Not just math and scientific libraries. Even a simple reusable data structure.
And fact it's so commonly needed for this, that Go's slices and maps would
have been useless unless Go's designers have not cheated and used genericity
for themselves...

And let's not get into reusable abstractions for behavior -- like a library
that encapsulates the 5-10 more common uses for channels and goroutines (span
N goroutines and wait for all to collect the results, span N and use first
result, and so on).

------
AlexCoventry
In Swift, what's wrong with writing the imperative version to start with, then
switching to the monadic version as there's time to polish, or as the function
logic evolves to a point where other styles are clearly preferable?

~~~
tptacek
Nothing at all. His point is just that there's cognitive burden associated
with making those kinds of decisions in Swift, and there isn't in Go, because
you don't have those options. All things considered, he prefers Swift. But
he's productive in Go as well.

I've had similar experiences. I find that for some problems --- not all of
them --- I can drill in quicker in Go, because the problem is all I can really
think about; there isn't enough elbow room in the language to really spread
out and work on the task of making things elegant.

At my last company, I found that writing an emulator in Go was super
straightforward, and I think Go made that task easier than a "better" language
like Clojure or Swift would have. But in addition to an emulator, we also
wrote a compiler, and writing a compiler and SSA optimizer in Go was fairly
unpleasant. Not prohibitively so, but enough that I noticed it.

~~~
danenania
I think it’s kind of akin to the premature optimization people do when they
think they have ‘big data’, but really don’t.

If you’re really doing heavy list processing, transforming complex data
structures, etc., then you’re probably going to miss map, reduce, and friends.
But for most real world problems, the code is faster to write, faster to run,
and easier to understand with a few dumb loops.

It’s always tempting to do things the clever way, but Go made me realize how
rarely it’s actually beneficial.

~~~
wolf550e
For compilers and optimizers, people have said pattern matching support in the
language is very beneficial. I bet there are other tasks where something like
algebraic data types and pattern matching would make the code much simpler,
and it's not really hard for the language to implement.

------
stouset
The title of this submission reads like a No True Scotsman fallacy.

------
jmull
I think this is from 2014?

Anyway, it hardly seems fair to give yourself choices (by introducing that
“LlamaKit” library) and then criticizing Swift because there’s different ways
to approach the problem.

(And I wonder if LlamaKit does anything besides obfuscate code? Hopefully I’m
just missing some context.)

~~~
tptacek
He's not criticizing Swift. He's a Swift programmer who prefers working in
Swift to working in Go.

------
mda
it impossible to not roll my eyes when i read such a title.

------
otterley
Flagged for changing the blog post subject to clickbait.

------
kodablah
> Very cross-platform out of the box. Not “sort-of cross-platform as long as
> it’s unix” like C/C++

Wut? Firstly, no it's not. I have to drop into MinGW just to interface with
native libs statically. Many languages don't do this. Secondly, C++ is very at
home on Windows. Not a very good FFI story for something that is very cross-
platform that it only binds w/ C libs with only one Unix compiler (gcc). It's
like you got the phrasing exactly backwards and need to switch Go and C/C++.

> Go feels under-engineered because it only solves real problems.

Until I list the ones it doesn't. Or are they not "real"?

You know what? I'm not reading these things anymore. We know the
type...supposedly senior devs writing a bunch of words about one language over
another, cherry picking specific things for both to fit the narrative. I feel
like this is how Michael Moore would write blog posts comparing languages.
Sorry to hop on this article like this, saw it a couple of days ago with the
Java/Kotlin blog post too and I'm seeing it every so often. And I like Go and
Java. I'm afraid I just don't see these language opinions as that valuable
anymore since I write in them all myself and know better.

Edit: In retrospect, probably a bit harsh. But I'd prefer the journalistic
lang X does this but not this approach over the op-ed.

~~~
tptacek
I'm an old C++ programmer who's had the pleasure of doing an XP codebase and I
would pick Go any day of the week over the early-aughts C++ I remember working
in --- but I concede this may have gotten better since then.

While I don't think he was trying to say Go solves _every_ real problem
(rather, just that the subset of problems Go solves are all practical and not
theoretical), it would be constructive if you could take the time to list the
problems you think Go is bad at solving, and why.

I'll probably agree, but I may also learn something, and I'll _definitely_
learn more about where you're coming from.

~~~
kodablah
While I would choose Go too, my specific complaint was about saying that Go is
very cross platform and C/C++ are only sort of in a Unix way. Not only do I
think Go has cross-platform issues wrt Cgo and that they only support gcc (but
hopefully changing [0]), but that it is incorrect to say C/C++ is "sort-of
cross-platform as long as it's unix". Those types of statements turn me off
the article. So I stopped reading after that and the "real problems"
statement.

I'm not sure it has much value to list places where Go may not solve the
problem because we all know the limitations of our
languages/platforms/runtimes. Among places Go is not the best: low-level
embedded software, very performance critical software, software static
correctness is more important than maintainability, etc. It's like saying Rust
solves all real problems. While I guess mostly true, it doesn't mean too much
to me. In general, I'm just finding these posts have little value to me
anymore.

0 -
[https://github.com/golang/go/issues/20982](https://github.com/golang/go/issues/20982)

~~~
skybrian
This is just disagreeing on definitions. You're assuming a particular
definition of "cross-platform" and I think what they mean is that pure Go
(using its standard library) is very portable. It's great if the standard
library does what you need.

~~~
detuur
A portable stdlib does not a portable language make.

------
amzans
Edit: I had used a quote from the blog post as the title, but updated it to
match the blog post as I realised it was a mistake.

The original title was: "Go feels under-engineered because it only solves real
problems".

------
teddyh
Go might be nice and all, but I could probably never in good conscience use it
seriously, for one simple reason: It’s dominated by Google. It was started by
Google, and all of its core development (I assume) is done by Google people,
with Google’s blessing. It’s even _named_ for the company, making the
ownership transparent and obvious to all.

With something like C, C++, Lisp, Python or the like, you _know_ that even if
some large company abandons it, it probably won’t even make the headlines,
since it won’t matter much for the rest of the users of the language – it has
a large enough user base that the language will be fine.

But what if the controlling company decided to abandon Dart, Swift, C#, Go,
etc.? It would kill the language in an instant. Or if they decided to simply
take the language in a new direction more suited to the company but contrary
to the wishes of its global user base? I can’t work under those conditions,
and neither should anyone else accept to do so.

To clarify: _If_ , say, _at least_ two thirds majority of the development of
the language was no longer done by a controlling company (and if the
supposedly non-affiliated developers were not also all incidentally employed
by the same company), and, in the case of Go, the name was changed, I would
probably not have a problem with using any of the aforementioned languages.

P.S.

Rust is a slightly special case, since it’s dominated not by a company, but by
the Mozilla _Foundation_ , making it slightly more dependable than an
arbitrary company.

~~~
coldtea
> _Go might be nice and all, but I could probably never in good conscience use
> it seriously, for one simple reason: It’s dominated by Google. It was
> started by Google, and all of its core development (I assume) is done by
> Google people, with Google’s blessing._

I don't think Google is particularly the problem here. Go has lots of people
working on and with it from outside Google.

The problem is that the core team is very resistant to any kind of outside
ideas (while not being always brilliant with their ideas to compensate) -- and
the community has fossilised to those loving the same ideas as well. It
encourages a groupthink that's not there in other languages.

Contrast with e.g. Swift, which while run by Apple, has a great community
participation story (to the point to going into too much bikeshedding).

~~~
p_l
A significant part of it is that there's a disconnect between a bunch of the
core team, and the rest of the world, because even said fossilized group of
the community often has no idea about certain Go fundamentals (like that
significant portion of the runtime is copy-paste rewrite of certain C
libraries, libs that even were part of the runtime before the rewrite, and
that Go is verily not unix/posix native language).

