Monday, March 19, 2012

Some thoughts after using Go for a couple of days:
  • I like gofmt.
  • Having used Java for so long, I got tripped up by the passing by value of structs and had to change the parameters to pointers.
  • I also got tripped by the := declaration shadowing variables:

    func pop(n int, list []int) ([]int, error) {
    if n > len(list) {
    return list, errors.New("error")
    }
    return list[n:], nil
    }
    func multipop(counts []int, list []int) ([]int, error) {
    for _, n := range counts {
    list, err := pop(n, list) // Oops, a new variable named list
    if err != nil {
    return list, err
    }
    }
    return list, nil
    }
  • I like goroutines + a channel better than java.util.Iterator and Python gemerators, but not as much as lazy lists in Haskell for producer/consumer code.
  • containers/list looks very awkward compared to java.util.List, especially with Java generics. Generics are almost essential for useful containers, so Go inelegantly has the built-in function append and the built-in map data structure.

Monday, March 12, 2012

I've been thinking about playing with Go for a while, as it seems worth knowing, so I decided to install the compiler. That was a bad experience. I didn't want to install Mercurial to get the sources, but there was tar file available for download of the most recent weekly snapshot. There didn't seem to be a more stable version available. So I downloaded it and built it. It failed on some ipv6 tests, so I commented those out. Then, it went into some infinite loop or something is another test, so I killed it after about 15 minutes in that one test, and downloaded and installed a pre-built binary package instead. That was a mistake. Somehow, after installing it, /etc was empty except for /etc/paths.d/go. Apparently, on a Macintosh, /etc is supposed to be a symlink to /private/etc, and the go install screwed that up. And I couldn't even run sudo or su to fix it, since /etc/pam.d was gone. I had to reboot into single user mode to fix it. After all of that, the binaries still didn't work due to some dynamic link error. Probably because I'm using an older version of the operating system. In the end, I figured that I could still use the build from the sources, even if the tests didn't run, and was able to build a hello world program.

Here are some of my first impressions. Go seems to me to primarily aimed at what C++ (and Java and C#) is used for, as well as being designed to appeal in particular to those who prefer using Python (and Ruby and Javascript). I like that it has static typing. To me, the syntax is just another not particularly elegant syntax. The concurrency model of goroutines and channels seems similar to Control.Concurrent.forkIO and Control.Concurrent.Chan in Haskell, but it also has shared memory and explicit locks like Java does, though that is discouraged in favor of using channels in idiomatic Go. Go does not have software transactional memory. Overall, it feels driven by pragmatism over elegance. I think I'd prefer using Go over C++ and Python, possibly in time over Java, but not over Haskell for most things I'd do.