The Most Intriguing Concept In Google’s Go Language

Writing

If you have been anywhere near the geekier parts of the internet lately then you are probably numb from hearing all the chatter about Google’s new language called "Go". I saw a few links to it from reddit, and I thought, "yay, another language to look at." Yes, that is actually what I thought, I know, I’m weird. Upon reaching the Go site, and doing a few quick cursory glances, I found myself quite repulsed. And I don’t mean repulsed in that it is a bad language, but repulsed in that it is a language which is designed for a world entirely outside of the one that I work in on a daily basis.

I mean, Go looked ugly to me. Sure, Rob Pike and Ken Thompson were working on it, but that is exactly the reason why it is so hideous to me. They are hardcore C and Unix kernel types guys, whereas I like my languages to be a little higher level. I want my languages to lean more heavily in the “developer productivity” camp, rather than the "machine productivity" camp. But to be fair, Go is a systems programming language, and so after reading their goals for the language I feel that they are heading in a really good direction (Not that they care at all how I feel).

Digging Further

Despite my misgivings, and my lack of interest in actually using the language, I decided that I would read on a bit further and see if there was anything that really stood out to me about Go. I started reading that it had pointers, but not pointer arithmetic, meh. It has some interesting concepts around slices, meh. They have a concurrency model called "goroutines" that talk to each other through a message passing system called channels, meh. All of this I had seen before in many popular languages. So far I wasn’t really blown away…

But as I read through the Go language design faq, I came across this sentence:

And perhaps most radically, there is no type hierarchy: types just are, they don’t have to announce their relationships.

Now that is cool. Go is an object-oriented language without a type hierarchy. You might be wondering how that would work. How can you possibly have an effective object oriented language without a type hierarchy? You may also be thinking to yourself right now, "But isn’t the bedrock of object oriented systems inheritance?" And to be quite honest, a few years ago I would have thought the same thing. The reality is that inheritance is not the only mechanism of reuse in object oriented languages. Over the years, after much trial and tribulation, along with the guidance of many people who are much smarter than I am, I too have seen the light that composition is a much more powerful mechanism for sharing behavior than inheritance. It appears that the designers of Go feel the same way, and strongly enough to drop inheritance entirely.

Composition Versus Inheritance

Go allows you to have types which contain data and methods that operate on that data. It also allows you to create interfaces which you can place on those types. If you think about it, this is really all of the functionality that you need in order to recreate all of the behavior that we have in object oriented hierarchies. Think about that for a second, what does the naive developer do when he wants to create a new custom collection type? Does he simply inherit from the base collection type and override the methods that he needs? Well, this may be fine if you want to override every method in the base collection type and guarantee that you have not broken behavior in any way, but a more seasoned developer is likely to use composition and wrap a collection type and then expose only the functionality the he needs.

So instead of:

public class CustomCollection<T>: Collection<T>
{

You could do something like this:

public class CustomCollection<T>: IEnumerable<T>
{
  private Collection<T> wrappedCollection = new Collection<T>();
  
  public void Add(T item)
  {
    wrappedCollection.Add(item);
  }
  
  public IEnumerator<T> GetEnumerator()
  {
    return wrappedCollection.GetEnumerator();
  }

  IEnumerator IEnumerable.GetEnumerator()
  {
    return GetEnumerator();
  }
}

Now, it would be nice to have some sort of interface delegation mechanism in place so that I don’t have to put methods in to pass calls from the external interface to the object which is being wrapped, but that is an argument for another time.

Interestingly enough, in Go, interfaces are implicit. You can define and interface and a type automatically implements this interface if it satisfies the interfaces conditions. This is what the sentence I quoted above meant when they said that types don’t announce their relationships. This really gives a very dynamic feeling to a statically typed language.

Is This The Right Way?

I honestly don’t know. If Go catches on it’ll be interesting to see how much of an issue not having a traditional inheritance model creates for them. There aren’t very many widely used object oriented languages which don’t have a hierarchical inheritance mechanism. Off the top of my head, javascript is the only one I can think of and most people don’t use its prototypal inheritance model at all. But for those who do use it, it seems to create a better model for flexibility, composability, and reuse. Only time will tell whether this is a good design decision from the Go team, and I for once will be eagerly anticipating what comes out of it.

But This Is A Systems Language!

So before people go on harassing me about how many other cool things there are in the Go language, I’ll just say right now that many of the features that they are implementing in Go are fairly revolutionary for a low level programming language. Sure, some of this stuff has been done in D, and probably a few other languages, but they are really pushing the bar for a low level systems language. I think that is awesome! However, I am looking at this from a person who has been using high level, safe, garbage collected languages for many years now, so much of this is old news to me. In the low level world of systems programming though, these types of changes would likely be revolutionary.

Summary

I look forward to the evolution of Go, and in particular, which direction they take regarding generics and an exception system. Currently Go has neither because the language designers don’t yet understand whether they are needed, and if they are, how they can be worked in without sacrificing the relative simplicity of the language. I hope that this post has piqued your interest in Go just a little bit, and I encourage you to go check it out (pun intended).

Loved the article? Hated it? Didn’t even read it?

We’d love to hear from you.

Reach Out

Comments (8)

  1. I agree. I am not interested in Go either, at least not in using it. I do think that it has some interesting features, esp. for a low-level language, as you say. But there’s nothing earth-shattering about it. If it’s true that all languages will eventually (d)evolve into LISP or Fortran, I wonder which one Go will become. 🙂

  2. [quote]Now, it would be nice to have some sort of interface delegation mechanism in place so that I don’t have to put methods in to pass calls from the external interface to the object which is being wrapped, but that is an argument for another time.[/quote]If I understand you correctly this is available in Go. See this thread in the mailing list:

    http://groups.google.com/group/golang-nuts/browse_thread/thread/ef9a04aa05289ae8

    The example shows that if a type has as the first member an instance of another type then methods called on the first type will delegated to the contained type.

  3. Haskell’s type classes are a quite different beast really:

    * a method of a type class can take any number of parameters of the given type (i.e. zero, one, two etc.), rather than just one. These methods are pretty different from OO-style methods.

    * a data type only belongs to a type class via an explicit definition of the methods. (or an explicit ‘deriving’ clause, which gets the compiler to write the methods for you).

    Haskell also does not have OO-style inheritance, but that’s because it’s not an OO language 🙂

    Type classes themselves can belong to inheritance chains (i.e. the interface, not the type), which is the only way a type can be an instance of a type class without an explicit declaration — if type x belongs to type class Foo, and all types belonging to class Foo are also defined to belong to class Bar, then x belongs to Bar too.

  4. This sounds a bit like the type system for objects in OCaml: subtyping is structural, in the sense that you don’t care about inheritance, you just check all the methods and fields are there, with compatible types.

    Inheritance exists, but just as a shortcut to write code: you can always override a method with one that has an incompatible type. You just don’t have to type the code for the things you don’t overwrite.

    The lesson (which seems similar to Go) is that inheritance and subtyping may be two completely different things.

Leave a comment

Leave a Reply

Your email address will not be published.

More Insights

View All