Thoughts on Go

So I’ve spent a day with Go. Here are my thoughts on it so far:

Language

  • +1: It seems to allow for much terser code than C. Most code I ported over was around 50% of the size which is interesting. Some things that help Go in this regard are multiple return values and the much greater ability to express & use struct literals. For example, stuff like this feels natural after a while as a shortcut of allocating a Foo structure, filling it in and then returning it. This is typically done over many more lines in C:
    return &Foo{
      Bar: a + someFunc(b),
      Baz: "frob",
    }
  • +1: The := operator is great, like C++’s auto or C#’s var but even terser. Fantastic that it works for multiple return values as well.
  • +1: Variable declarations in if statements combined with a test is a great way to keep code short & to the point:
    if foo := someFunction(a, b, c); foo != nil {
      // code to use non-nil foo goes here
    }
  • -1: I’m not a great fan of using the casing of identifiers for controlling privacy, exporting or anything else in fact. While it enforces consistency, it also forces you to edit lots of locations if you want to make public a variable that has previously been private and vice versa. -1 on this.
  • Just weird: forcing an indentation & layout style is close to Python creepy. I like K&R though, so I’m fine with the choices they’ve made. I’m not sure I want the gofmt program to tabulate my comments and structure fields though.
  • -1: I always find it lame when there’s no way to replicate what looks like regular functions or patterns provided by the runtime in the language itself. A good example is the append() function which the documentation clearly states cannot be written in Go, as there are no generic types. The same goes for the map & slice objects which have custom syntax and behave generically, but you can’t do the same thing with your own stuff. That means someone on the language design team has to add your feature to the language in order for it to happen, which it won’t.
  • +1 The defer statement is a nice substitute for RAII, using and other hard-coded solutions. It doesn’t beat Lisp’s defmacro though 🙂
  • -1 The import mechanism feels clunky with string identifiers that are similar to paths. Are they paths? How do they interact with the compiler’s search directories? When is “./foo” needed? Would have been nice with more explicit control & more search directories.
  • +1 Proper closures, awesome! Really great to be able to nest functions and refer to enclosing scopes transparently. This removes so much junk for callbacks.
  • -1 No way I’ve found to do efficient I/O of binary structures. The encoding/binary package uses reflection and type switching for every field.. Ouch! To get some decent speed it would be nice with something similar to C#’s fixed and a regular cast. Will probably not happen as the language doesn’t even have unions.

Ecosystem & Implementation

  • -1 The packaging & build mechanisms leave a lot to wish for if you’re trying to build a program using a set of locally defined packages, say for utilities in a bigger program. The default behavior of the suggested makefiles copies your libraries into the system-global Go root. Who wants to copy a broken in-development library into the system Go install dir, leaving junk files everywhere!? The default Make behavior here should be helpful to Go users, not Go maintainers who should hopefully be in lesser numbers and know how to override the defaults.
  • -1 Related to above, would have wanted the ability to say “these three files compile together as a package” rather than having to be forced to put them in their own directory. This is almost as stupid as Java’s class/directory path handling. The compiler can totally do it so this is purely a infrastructure thing.
  • -1 Saying “Memory allocation is too hard & a waste of time, let’s use GC, modern GC’s are great!” and then shipping a really old, bad stop-the-world GC doesn’t exactly give me lots of confidence. How will a future threaded GC interact with the memory model? I remember the pains Java went through when JVMs started doing incremental, threaded GC.
  • +1 Compile times have been great so far. Not much difference from C though, but plenty faster than Mono. (This is on OS X.)
  • +1 The standard library is surprisingly comprehensive for a language this young.
  • -1 Only static linking, and even hello world programs are huge. Caused by early tech & no dead stripping, but a limitation for sure.
  • -1 The current thread scheduler is really crude, must use environment variables to specify number of cores.
  • +1 godoc is nice and seems to work well without lots of boilerplate in the comments.

To sum up I guess most of the ecosystem & quality of implementation issues are due to the relative young age of the language. The language itself is pretty nice to code in if you think about it as a cross of C and C#, basically C# without all the class & inheritance nonsense which is refreshing.

2 thoughts on “Thoughts on Go

  1. To respond to some of your negatives:

    “The import mechanism feels clunky with string identifiers that are similar to paths. Are they paths? How do they interact with the compiler’s search directories? When is “./foo” needed? Would have been nice with more explicit control & more search directories.”

    Yes, they are simply paths. Absolute paths (“foo/bar”) are relative to $GOROOT/pkg/$GOOS_$GOARCH/ while relative paths (“./baz”) are relative to the compiler’s CWD. The latter is rarely used. Most people prefer to use a GOPATH these days. See http://golang.org/cmd/goinstall/ for the details on goinstall and GOPATH.

    “forcing an indentation & layout style is close to Python creepy”

    When you have thousands of programmers and millions of lines of code, it really helps.

    “The packaging & build mechanisms leave a lot to wish for if you’re trying to build a program using a set of locally defined packages, say for utilities in a bigger program. The default behavior of the suggested makefiles copies your libraries into the system-global Go root.”

    Again, check out goinstall and GOPATH. They solve this problem. http://golang.org/cmd/goinstall/

    “Related to above, would have wanted the ability to say ‘these three files compile together as a package’ rather than having to be forced to put them in their own directory. ”

    We decided on one-package-per-directory as the convention, and it has been working well for us. What is your specific issue with it? (Note that this convention is only enforced by goinstall. There are other build systems that support mixing packages within files in the same directory. I think this can be confusing, though.)

    “Saying ‘Memory allocation is too hard & a waste of time, let’s use GC, modern GC’s are great!’ and then shipping a really old, bad stop-the-world GC doesn’t exactly give me lots of confidence. How will a future threaded GC interact with the memory model? I remember the pains Java went through when JVMs started doing incremental, threaded GC.”

    Java programs tend to generate a lot of garbage. This is an unfortunate fact of Java’s object model. Go programs tend to use a lot less memory than Java to store similar data structures, and can be easily tuned to reduce the amount of garbage they produce. There is plenty of room for improvement with the current Go GC, but we haven’t found it to be a bottleneck in real software yet.

    “Only static linking, and even hello world programs are huge. Caused by early tech & no dead stripping, but a limitation for sure.”

    The size of statically-linked binaries is comparable to statically-linked C equivalents. Most of the bloat in Go binaries is the result of reflection. Believe it or not, where we come from (Google) Go binaries are considered very small. 🙂

    “The current thread scheduler is really crude, must use environment variables to specify number of cores.”

    Rather than “crude” I would instead say “simple.” It works well, and we haven’t chosen an arbitrary heuristic to choose GOMAXPROCS. Instead we leave it to the developer to choose an appropriate value for their program.

    Happy to answer any questions you might have.

    Cheers!
    Andrew

    • Thanks for a great reply Andrew!

      I hadn’t seen GOPATH, so my experience was with the stock Makefiles and suggested setup that comes with the language distribution. Next time I check Go out, I’ll make sure to try GOPATH as well. Would you say it’s focused more to build foreign code or also a way to organize your own project into sub-modules?

      My issue with requiring a file layout is that it is orthogonal to what the compiler is doing and doesn’t have anything to do with the process of compilation. Java has this issue on a package+class level, and now every java project begins with 3 or 4 empty directories. I believe file structure and workflows are best determined by the people writing the code, so although the Go structure is less rigid than Java I still don’t like it. A less intrusive alternative would have been to require batch compilation of all related files in a library similar to how C# works and not care what the paths of the individual files are.

      For an example of why I think fixed build rules are bad, consider the case where you want to code-generate a set of Go files for different libraries. With the current build requirements, you can’t keep those generate source files in the build directory, they have to be copied into the source directory which conflicts with version control and build hygiene, or you have to copy your entire source tree to the build directory which can mess up debug information and so forth.

      Agree about Go might use less garbage than Java, but from what I can tell the reflection API, interfaces and auto-boxing means there’s still much more heap activity than in the typical C program if you write code in an idiomatic Go style. This being the case I’m not going to be satisfied by the “leave it to the experts” attitude until there’s a efficient, tunable, multi-threaded GC implementation available on all platforms.

      Cheers,
      Andreas

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s