
Channels in Golang - bsg75
http://www.tapirgames.com/blog/golang-channel
======
Animats
Channels in Go turned out to be less useful than expected. The original pitch
was "share by communicating, not by sharing". But in practice, large amounts
of data tend not to be sent over channels. It's common to send references over
channels instead, which implies sharing across goroutine boundaries. Go
doesn't have strict single ownership, like Rust, so you can send something to
another goroutine without the sender losing access. This creates a potential
race condition. (There are checkers for detecting this at run time, but it's
not a compile time error, as it is in Rust). Channels are thus equivalent to a
queue module coupled to a lightweight thread system.

Go is garbage-collected, with a good concurrent garbage collector, so all this
is memory safe. Mostly. Maps (Go's dictionary type) aren't concurrency-safe
for performance reasons, and there's an known exploit involving slice
descriptors.

~~~
eloff
Furthermore, channels are slow. I only use them when performance doesn't
matter, and even then I end up rewriting them into a mutex half of the time
and simplifying the code in the process. It was a nice idea in theory, but the
implementation is full of usage pitfalls and performance issues.

I use queues of my own implementation when I really need performance. But then
I have lots of experience with that, and I have the implementation of maybe
the world's highest throughput SPSC queue, outperforming the Lynx queue that
was featured here on HN earlier in the year. I'm still trying to make time to
write that up properly as a blog post (I hate writing blog posts.)

~~~
netheril96
Maybe you should contribute to the go development to improve the performance
for everyone.

~~~
eloff
They have Dmitry Vyukov, who's better at that kind of thing than me. If they
want to fix the problem, they don't need my help. I would rather publish my
work, and if they want to adapt it for Go's channels, they can do that with my
blessing.

To me the tricky part seems to be how they need an implementation good for all
cases. Performance engineering is all about tradeoffs. Memory usage,
throughput, latency are often competing requirements and you have to choose
one. Furthermore, unless they can somehow statically determine how many
threads access a channel, they have to use a MPMC queue, which is a
performance anti-pattern.

I would modify the language (maybe just make() builtin) to allow specifying
what type of Channel is needed where, SPSC, MPSC, SPMC, etc. But we all know
how that would be received.

~~~
zzzcpan
If you control both the compiler and the scheduler these optimizations become
somewhat easier and without any syntax changes, no? Like removing naive
synchronization on channel operations and having scheduler to deal with them,
tracking states, amortizing synchronization, etc.

~~~
eloff
Some become easier, yes. But I don't think it's that easy to tell how many
threads access a channel. We have runtime race-checkers precisely because we
don't know how to check that at compile time. Whether the specific case of
channels in Go is easier, I don't know. You can in Rust because the language
makes you specify which threads owns what and two threads can't own the same
thing at the same time (as I understand it anyway.)

------
sdegutis
My "aha" moment when trying to understand channels in Go was when I realized
that everything about how this feature is designed comes from their answer to
the question "how could we 'fix' select() in C?". In fact, pretty much every
feature in Go is designed to fix some perceived flaw in C, and that's the
entire philosophy behind Go. They aren't interested in language theory, or in
innovating or solving problems outside of C. They were just trying to write C
2.0. Not that that's a problem, it's just, it threw me off. When it came out,
I fully expected Go to be a new competitor to Java or even Python, not to C.

~~~
tapirl
yes, Golang is really can be viewed as c plus. But it also absorbs many
features from other languages.

Personally, I think Golang is a Java killer. I never write one line Java code
since I became familiar with Go. The main reason is it is painful to maintain
a Java web project, slow compiling, slow startup, large memory consuming, so
many concepts (of all sorts of frameworks) to learn, etc.

~~~
seabrookmx
While I'm sure many people will agree with you, I (respectfully) don't for a
couple reasons..

Golang doesn't have the library or tooling maturity or breadth to make it a
real competitor to Java in the enterprise space IMHO.

Golang lacks a package manager (and "go get" is not a real substitute when it
completely shirks semantic versioning). There's no solid IDE with Golang
support. Most of the web server and database tools are very low level, and
while they provide the necessary features for a smaller project or if you're
writing exclusively microservices, they leave a lot be desired if you're
writing a run of the mill web app, or an enterprise system for batch
processing (orders, transactions, email etc).

For smaller projects, most languages are better than Java for the reasons you
mention (including dynamic languages like Python for example). Golang is a
novel language and it definitely has a niche, but I find it right inbetween a
language like Python and a "heavy" language like C#/Java.

~~~
wcummings
I'm not really a go person. I might go as far as saying I'm a go hater. But I
feel compelled to defend it in this case. Golang is a deliberately simple
language that lends itself well to inspection & tooling. For example, having
special syntax for returning errors vs a more generic solution like multiple
return values or returning a tuple. It feels awkward but makes detecting
unhandled errors very simple.

Seems like there's decent enough tools + emacs/vim wrappers to me. In my mind
this is one of the primary merits of go.

~~~
pcwalton
> For example, having special syntax for returning errors vs a more generic
> solution like multiple return values or returning a tuple.

Even if this were true (which it isn't—Go uses multiple return values for
returning errors), returning a tuple would in no way make analysis harder.
Detecting whether a function returns (T, err) for some T is utterly trivial.

------
ridiculous_fish
Why are functions like cap, len, and close builtins instead of library
functions? Is it because they have to be generic over channel types?

~~~
hamandcheese
Because the creators won't give us generics

~~~
dispose13432
I know it's a controversial point among users, but I think that if Generics
were such a show stopper, Google would have implemented them.

Go was invented for internal Google use, and then shared with the world, and
Google is an engineering company. If engineers would have rebelled, higher
management probably would have done something about it.

\-----

Although I don't understand why they keep fighting it. A simple style generics
(Java style) shouldn't make code _that_ ugly.

~~~
closeparen
Do we know that Google actually uses Go extensively? AFAIK the Downloads web
server is the only piece of Google publicly disclosed to be written in Go.

IIRC most of Google is C++ and Java, which both have generics.

~~~
dispose13432
I don't think they created the language for _fun_.

I read somewhere that they have a lot (I _think_ it was in the MLOC range) of
proprietary/in-house code written in go.

~~~
mseepgood
[https://talks.golang.org/2016/applicative.slide#9](https://talks.golang.org/2016/applicative.slide#9)

------
duaneb
If anyone has a clue why this was downvoted, please clue me in. It was on
topic and indicating missing information.

Edit: I really don't care how much I get downvoted, I'm going to highlight its
uselessness until someone cares to justify it.

~~~
duaneb
We should really require commenting while downvoting unreplied comments. The
community has gotten lazy.

