Live data from Hacker News

The Beauty of Concurrency in Go

pragprog.com

21–30 of 95 posts

Re: The Beauty of Concurrency in Go

#21

This article and many like suffer from one of my huge pet-peeves, absolutely terrible coding conventions. I am a person who likes to scan articles, I'm busy and generally make a read now, read later, read never decision. The code from first scan was unreadable, short 1 character variable names, "why is there a hardcoded date marked 2006.01.02-15.04.05 there??", etc. Readable code takes a little more time - but it's w…

I'm afraid many of the conventions you complain about are standard Go, err, conventions... (Although see my complaint elsewhere.) Because they are so widely used, people who use Go won't bat an eyelid. Unfortunately that doesn't make the article a great introduction to Go.

I hope these talks can help sell you on Go http://blog.golang.org/2013/01/two-recent-go-talks.html

To be more explicit:

Short variable names generally reflect the idea that you know what a variable is for just by knowing its type. Thus you have a file named f, a time t, a variadic argument called v. When the type is not enough, a longer name is recommended. Naming things is hard though...

The hardcoded date is a wonderful piece of the time package, which I fully appreciate will look bizarre at first. (And therefore isn't a great thing to use in a first look at Go, without explanation). See the official documentation http://golang.org/pkg/time/#pkg-constants

Re: The Beauty of Concurrency in Go

#22
post #3

Ugh, I just finished writing the XMPP frontend for an XMPP/IRC bot I'm working on ( http://www.getinstabot.com ). The frontends are in Go for concurrency, and ferry messages back and forth from the channels to the backend. Let me tell you, that problem is hard . Go coped pretty well, but the final thing is a mess of global states, and it's pretty elegant for what the problem is. I was hoping to avoid having many movi…

> Something I miss from the language … Does sound like you want to use channels, and break your logic into small independent parts. You will have one goroutine using blocking Read() in a loop and feeding data to some channel. When it's done, you write to another channel that exists only for signaling: defer { doneChannel and then in your other goroutine: for { select { case data := The only things shared here are the…

> I know I can use "chan struct{}" to avoid any storage, but I think "I disagree. struct{}{} tells me that the value isn't important. Whenever I use map as a set, rather than a key-value store I use map[string]struct{} (say), rather than map[string]bool. Then I am forced to use the double assignment to check for membership of the set. And that's exactly what I want. I'm able to make my intent more obvious in the code I write. No one will ever look at it and say "but what if it's false?" - I dislike using booleans instead of empty structs in the same way I dislike other C programmers using integers as booleans.

Re: The Beauty of Concurrency in Go

#23
post #22

Earlier quoted context omitted.

> Something I miss from the language … Does sound like you want to use channels, and break your logic into small independent parts. You will have one goroutine using blocking Read() in a loop and feeding data to some channel. When it's done, you write to another channel that exists only for signaling: defer { doneChannel and then in your other goroutine: for { select { case data := The only things shared here are the…

> I know I can use "chan struct{}" to avoid any storage, but I think " I disagree. struct{}{} tells me that the value isn't important. Whenever I use map as a set, rather than a key-value store I use map[string]struct{} (say), rather than map[string]bool. Then I am forced to use the double assignment to check for membership of the set. And that's exactly what I want. I'm able to make my intent more obvious in the cod…

> I dislike using booleans instead of empty structs in the same way

Eh? If you have `map[keyType]bool`, then a key lookup is simply the set membership function. If a key exists, it returns true. Otherwise, false. That certainly doesn't seem analogous to abusing integers as booleans...

Re: The Beauty of Concurrency in Go

#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 Go's tooling is nonexistent, there is no IDE to do this automatically for you.

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.

Re: The Beauty of Concurrency in Go

#26

This article and many like suffer from one of my huge pet-peeves, absolutely terrible coding conventions. I am a person who likes to scan articles, I'm busy and generally make a read now, read later, read never decision. The code from first scan was unreadable, short 1 character variable names, "why is there a hardcoded date marked 2006.01.02-15.04.05 there??", etc. Readable code takes a little more time - but it's w…

> Even further, message passing!

I really like how Go does message passing, and other than channels being first class types, I don't think that's really the "killer feature" of Go. The killer feature is that goroutines are green threads, scheduled in M:N fashion on to OS threads. This encourages concurrent programming because spinning up a goroutine is comparatively cheap to spinning up an OS thread. It's difficult to do this kind of programming in most other languages (sans Erlang, Rust and Haskell).

Joe Armstrong made this argument years ago. He compared the limited ability to start processes in most languages as being similar to limiting how many objects you could create in your program.

If you want to see examples of concurrent programming in Go, go straight to the source: http://golang.org --- The tour is good, there are some codewalks, talks, articles, etc.

Re: The Beauty of Concurrency in Go

#27

This article and many like suffer from one of my huge pet-peeves, absolutely terrible coding conventions. I am a person who likes to scan articles, I'm busy and generally make a read now, read later, read never decision. The code from first scan was unreadable, short 1 character variable names, "why is there a hardcoded date marked 2006.01.02-15.04.05 there??", etc. Readable code takes a little more time - but it's w…

> why is there a hardcoded date marked 2006.01.02-15.04.05 there??

Date is not hardcoded, it's Go's convention of formatting date [1]

[1] http://golang.org/pkg/time/#Time.Format

Re: The Beauty of Concurrency in Go

#28
post #6
post #4

This has finally let me figure out what annoys me about Go, its a cargo-cult language. People saw that Erlang's Actors/processes were really popular and made it easy to write good, concurrent software. They then went away and implemented their own language with lightweight processes and message passing, but missed the fact that actors are the price you have to pay for the benefits of not sharing mutable data. And Go…

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.

Re: The Beauty of Concurrency in Go

#29

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…

Futures in C++11 are similar:

    int x = std::async([]()->int{
            return 100;
        });
    std::cout 
Which isn't as nice as closure. Go could probably benfit from having a standard futures tool. I guess something along the lines of:

    type Future {
        Wait() interface{}
    }

    func newFuture(func interface{}, 
                args ...interface{}) Future

Re: The Beauty of Concurrency in Go

#30
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.)

Post reply on HN