Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Go didn't invent co-routines, but the primitives of channels and the select statement that go along with them, while not ground breaking, amazingly simplify a lot of concurrency patterns that can get overly bloated and/or difficult to reason about in other languages.

I have simply never seen another language that makes it as easy as Go does to reason about parallelism/concurrency (maybe Erlang).



Languages don't need to make parallelism and concurrency easy if they're sufficiently expressive by themselves. Go bakes in things that a competent programmer doesn't need baked, while ignoring things that make a competent programmer better at their jobs (yes, it's the generics problem again!). Making channels primitives isn't a positive to me when it's something I can implement as well or better in userland--which I can, even in a language as middling and Java-1.1y as Go.

Go's channels are effectively a locking message queue (Java's had one of these since at least Java 5) plus a (usually global) thread pool. Not too long ago I implemented the moral equivalent in C++11, using only the standard library and in a unit-testable format, in forty-eight lines. Selecting across them is nice syntactic sugar, but is likewise able to be mimicked in plenty of other languages. Or, alternatively, I can use way more pleasant abstractions like Akka or Celluloid in not-Go languages (sending up Erlang when Akka provides a very similar experience in Scala or Kotlin--even Java, if you're using Java 8--is...curious).

I guess you can make an argument for TOOWTDI, but I don't find that to be persuasive when the OW in question is middling.


This is an attitude I've encountered before & can't really get my head around. Channels are a really bad implementation of a queued message concurrency pattern that has been standard in other languages for years.

The select pattern maps directly to any number of interupt style programming abstractions that are available in every language I've programmed in the last 15 years.

Quite simply I find the go concurrency story primitive to the point of painful. I'd love to figure out why my opinion on that is so far outside the common refrain


While channels definitely aren't anything new, and are just a renamed locking queue structure, why do you say they're "a really bad implementation"?


They don't scale well because of lock contention, the syntax is missing standard concepts like timeouts etc, & the behavior around edge cases around initialization, closed channels, nil values etc is bizarre.


Aren't they "lock-free" though?


Not in the least. They are a thin veneer on top of a giant mutex.


That's quite disturbing :P Any idea why they didn't implement channels as a lock-free list, ala java.util.concurrent.ConcurrentLinkedQueue?


I don't presume to speak for Go's developers, but I would guess because it's not that big a deal, especially in a cooperative environment. "If I can't obtain the mutex, yield" is a perfectly defensible thing, and is easier to write and probably to maintain than a lock-free list.

Having Java's concurrent stuff is nice, don't get me wrong, but I can understand it not being the biggest priority in the world to go rebuild that later. As I've mentioned elsewhere in this thread, there are much bigger beefs.


What other mainstream programming language has a queue pattern built right into the language itself?


What is the value of building something like that into the language? Why should a language have a "queue pattern" built into the language itself? Go has to have channels as a primitive to be usable in 2015 because its lack of generally-accepted features makes it impossible to do the same in userland. Same with its lists, same with its maps. I don't need it built into C++ or Scala or Java/Kotlin or C# or D, because these languages aren't unwilling to let me do it myself (but in all cases there are standard libraries to help me do it, even in the cases where it is not expressly already available).

You are implicitly casting as something to be praised one of the greater missteps of Go.


Missteps is a bit harsh, don't you think? Like them or not, channels and goroutines are quite integral to the Go language. And I think it's perfectly clear it's put in on purpose, and that it does guide the design of software written in the language.

You could perhaps compare it to Python, where async functionality has a solid and well established userland implementation in Twisted, but where asyncio still made a big splash around the community. Language constructs matter.


You misunderstand me. There is nothing in Go channels, syntactically or semantically, that is improved by being in the language itself, except insofar as the language does not provide meaningful and useful abstractions to its users to allow them to do it. I don't care why they say they did it, I care that it isn't very good and that I can't effectively replace it because the core developers don't give me the tools to do what is trivial in any other statically-typed language I see in common use. Channels and goroutines exist as core language features because the language is inexpressive because Go fundamentally does not trust end-use programmers to do smart things--so core developers had to do it instead.

"Misstep" was the kindest phrasing I had for the kind of trainwreckish design decisions and institutional reification of developer mediocrity that get you to what you're defending.

Your chosen tools have contempt for you, and it mystifies me as to why you would defend them for their failures.


Scala, Java & C# are all languages I've used professionally that have concurrent queues built into the standard library.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: