Live data from Hacker News

The Beauty of Concurrency in Go

pragprog.com

31–40 of 95 posts

Re: The Beauty of Concurrency in Go

#31
post #24

> > Notably, if a package is included but not used, Go treats this as an error and enforces removing unused declarations A good illustration that the Go designers didn't think their ideas through. This is a real pain in the butt when you are writing code and regularly commenting in and out sections of code while you are testing things. And every time you do this, you need to remove or restore the imports. And since G…

> A good illustration that the Go designers didn't think their ideas through.

Please don't misconstrue disagreement as sloppiness. If you read the mailing list, it's pretty clear they thought it through.

> This is a real pain in the butt when you are writing code and regularly commenting in and out sections of code while you are testing things.

Not for me. I love it, actually.

> And since Go's tooling is nonexistent, there is no IDE to do this automatically for you.

Vim does this for me.

Also, Go has some of the most wonderful tools of any programming language I've ever used.

> This kind of thing belongs in a compiler plug-in (if it was designed with such a thing in mind, which is not the case for Go), macros (if the languages supports them, ideally the hygienic and statically typed kind) or an external tool, not in the compiler.

I think reasonable people can disagree on this point.

Re: The Beauty of Concurrency in Go

#32
post #6

Earlier quoted context omitted.

Doesn't go just implement Hoare's communicating sequential processes, as does Erlang? They share the same inspiration. You don't need to share state data between your goroutines if you don't want to either just like you don't have to use mnesia to share state between erlang processes if you don't want to. I don't think you can really accuse go of being a cargo cult language either, Rob Pike has implemented CSP multip…

It is easy to accidentally share state between goroutines. For example, we wish to print out elements of a list: values := []string{"a", "b", "c"} for _, v := range values { go fmt.Println(v) } Each of these goroutines shares the same variable v, so this code contains a serious race condition.

It may be easy, but it's not that easy.

    values := []string{"a", "b", "c"}
    for _, v := range values {
        go func(){fmt.Println(v);}()
    }
Does have a race condition.

    values := []string{"a", "b", "c"}
    for _, v := range values {
        go func(s string){fmt.Println(s);}(v)
    }
Does not have a race condition.

Re: The Beauty of Concurrency in Go

#33
post #8

This article isn't bad... but it misses several important points of Go. I also note the article is 9 months old. In the hope that my criticism will be taken as constructive, with apologies for not writing detailed explanations: 1. Goroutines are not threads 2. type inference allows you to elide types in var declarations: var host = flag.String(... 3. Go's convention is to use camel case, not underscores. 4. Calling o…

How are goroutines not threads? Do you mean because it's possible for them to communicate without shared mutable state? Edit: Oh, apparently you all mean OS threads. So say so. (For example, in Haskell they're called threads without any implication that each one is an OS thread. Haskell's not unusual that way.)

goroutines are not threads because thread means something and goroutine means something else.

Re: The Beauty of Concurrency in Go

#34
There's so much code here.

If I weren't sick, I'd submit a new version that:

1. Didn't reimplement io.Copy

2. Didn't avoid io.TeeReader

3. Didn't do weird things to avoid regular channel ranges.

4. Didn't do non-standard date formatting.

5. Didn't reinvent the log package.

6. Didn't try to convince anyone runtime.GOMAXPROCS(runtime.NumCPU()) was a good idea (it's not)

In fact, maybe I will anyway. brb

Re: The Beauty of Concurrency in Go

#35
post #8

This article isn't bad... but it misses several important points of Go. I also note the article is 9 months old. In the hope that my criticism will be taken as constructive, with apologies for not writing detailed explanations: 1. Goroutines are not threads 2. type inference allows you to elide types in var declarations: var host = flag.String(... 3. Go's convention is to use camel case, not underscores. 4. Calling o…

How are goroutines not threads? Do you mean because it's possible for them to communicate without shared mutable state? Edit: Oh, apparently you all mean OS threads. So say so. (For example, in Haskell they're called threads without any implication that each one is an OS thread. Haskell's not unusual that way.)

Thread usually means an in-process concurrency construct controlled by calls to the operating system. A goroutine is managed by the Go runtime.

It's an important distinction between using many (read: hundreds) of OS threads in a single process isn't performant, while using hundreds or even tens of thousands of goroutines is just fine.

Re: The Beauty of Concurrency in Go

#36
post #24

> > Notably, if a package is included but not used, Go treats this as an error and enforces removing unused declarations A good illustration that the Go designers didn't think their ideas through. This is a real pain in the butt when you are writing code and regularly commenting in and out sections of code while you are testing things. And every time you do this, you need to remove or restore the imports. And since G…

False. The Go designers have explained many times why they made unused imports an error. In particular unused dependencies slow down compilation. There's even a FAQ: http://golang.org/doc/faq#unused_variables_and_imports.

A trivial workaround to silence the compiler errors during development is to use blank identifiers (http://golang.org/doc/effective_go.html#blank_unused). I use them all the time.

You may disagree with their decision, but it's disingenuous to claim that it's because they didn't think it through.

Re: The Beauty of Concurrency in Go

#37

Earlier quoted context omitted.

Sure, but what if you want to shut that goroutine down later on? The best solution that I've found is to just close the connection, the .Recv() will error out immediately.

What other solution would you want? You could use `SetDeadline` if you like. But closing the connection seems reasonable too. I think you're framing the problem wrong. You're not asking to shutdown a goroutine, you're asking "How do I abort from a synchronous read from a network connection that is blocked?"

Don't get too hung up on that, it was the least of the problems. Closing the connection works fine, it's just a bit unorthodox. The basic structure of the problem was much more problematic to implement.

Re: The Beauty of Concurrency in Go

#38
post #34

There's so much code here. If I weren't sick, I'd submit a new version that: 1. Didn't reimplement io.Copy 2. Didn't avoid io.TeeReader 3. Didn't do weird things to avoid regular channel ranges. 4. Didn't do non-standard date formatting. 5. Didn't reinvent the log package. 6. Didn't try to convince anyone runtime.GOMAXPROCS(runtime.NumCPU()) was a good idea (it's not) In fact, maybe I will anyway. brb

Here's the version I threw together in (what it says here), 12 minutes: https://gist.github.com/dustin/5478818

Re: The Beauty of Concurrency in Go

#39
post #34

There's so much code here. If I weren't sick, I'd submit a new version that: 1. Didn't reimplement io.Copy 2. Didn't avoid io.TeeReader 3. Didn't do weird things to avoid regular channel ranges. 4. Didn't do non-standard date formatting. 5. Didn't reinvent the log package. 6. Didn't try to convince anyone runtime.GOMAXPROCS(runtime.NumCPU()) was a good idea (it's not) In fact, maybe I will anyway. brb

> 6. Didn't try to convince anyone runtime.GOMAXPROCS(runtime.NumCPU()) was a good idea (it's not)

So what is an appropriate GOMAXPROCS? As someone who has only dabbled in a few Go tutorials, I would imagine that you would want GOMAXPROCS to be NumCPU() (or even greater) so the goroutine thread pool could "fire on all pistons". Why does Go's scheduler default to GOMAXPROCS=1 instead of NumCPU()?

Re: The Beauty of Concurrency in Go

#40

The beauty of concurrency in Clojure: ; Rough sketch: def defines a var (pretend it's a reference) ; @ is used to dereference the future and block to wait for the result. (def f (future (Thread/sleep 10000) (println "done") 100)) user=> @f done 100 ;; Dereferencing again will return the already calculated value. => @f 100 http://clojuredocs.org/clojure_core/clojure.core/future Edit: And more importantly, there are wr…

Go doesn't "force" you to use one method of concurrency.

It has more than one (you can do erlang-style share-nothing style or Java/C++ style of using mutexes to protect shared state from concurrent access).

I know nothing about Closure so it's possible it has more features but it's not necessarily a good thing. Is the complexity of 4 different solutions worth it? (by "it" I mean: a programmer has to learn all of them and when to use what; the implementor has to implement them; write wrappers for all standard data structures (what about third party libraries?) etc.).

Feature bloat has a cost.

Go gives you all you need to easily write concurrent programs and it does it with refreshingly simple design (both for people to learn and to implement).

Post reply on HN