Surprised by the Go programming language's treatment of nil

Go

So I happened to see an announcement of Go version 1.2. I saw something that disturbed me, having to do with nil, a “favorite” topic of mine.

What I know about Go

I don’t currently use the Go programming language, although there actually is a local Pittsburgh Go programming meetup group, the Go Steel Programmers, whose meetings I have never attended.

Some months ago I did, out of curiosity (and respect for any new language that I hear about people actually using to get stuff done), work through the tour of Go tutorial, to learn about the Go language. I installed packages on my machine, and wrote some compiling and running programs. I know just enough that I could code in Go for some project if I wanted to.

nil

What caught my eye in the Go 1.2 announcement was a note about changes in the semantics regarding nil.

For the record, I don’t believe any new programming languages should be invented that have the nil construct, Hoare’s “billion dollar” mistake. I’ve already previously given a talk about why, so I won’t repeat the arguments here.

But I think Russ Cox’s note about nil checks speaks for itself.

It said that Go 1.2 tightens things up so that various uses (directly or indirectly) of nil will cause a runtime panic rather than silently producing an unusable pointer.

Read that again: until Go 1.2, you could get silent bad behavior, an unusable pointer. This from a language that purports to be “statically typed”, improve on C, and provide memory safety guarantees.

Before Go 1.2, a chain of code involving a nil could result in behavior of which Russ Cox wrote:

The current behavior is at best merely historical accident; it was definitely not thought through or discussed.

There is also a note about a particular special case:

(it seemed like a good idea at a time)

You can read the whole document about nil yourself. You will find that it is still not a formal spec, but more a rationale of various special cases and possible implementation details.

C culture

Go arose from C culture. It was invented by those in C culture who wanted an improvement over the known problems of C. Unfortunately, I perceive it as today’s C, in the same way that the C invented in the 1970s was born with the problems that one could have avoided already at that very time.

Conclusion

The Go language continues to evolve, which is good, but I was surprised that the full ramifications of something as dangerous as rampant nil were not thought about up front.

Comments (7)Archived from Disqus

Yin Wang

I'm surprised too. That's unacceptable. But a special value nil can actually exist without problems and it's often even necessary. There are some languages with something equivalent to nil, but without null pointer exceptions, because they have union types. http://yinwang0.wordpress.c...

Franklin Chen

You're absolutely right, a language that had union types would treat null as something first-class rather than something implicit lurking around. And actually, the critique of null also applies to something like the standard critique of Haskell's lazy types, where bottom is always lurking around: http://existentialtype.word...

I haven't really looked at Ceylon http://ceylon-lang.org/ but it claims to support union and intersection types.

Yin Wang

Lazy types look a bit different. Having it explicitly typed will require lots of annotations from their origin all the way down to where they are used, much like async of C#.

PySonar had union types from the beginning although it's not a language. Type Racket has union types and intersection types. I'm using it for implementing my language. It works pretty well. I just took a look at Ceylon. It seems to be okay but not as simple as Typed Racket.

AreaMan

In the example in the referenced nil document, the error probably could be detected at compile time. Or clearly at run time by testing the nil-ness of the pointer x, as proposed in the document.

Go is being evolved slowly and carefully. Fixing the rare case of the bad nil is part of debugging the spec. Or maybe just the implementation. All good languages have areas that 'Need improvement'.

Franklin Chen

True, languages always evolve, and always have rough spots of one kind or another. But I think some transitions are more troublesome than others. For example, Java twenty years ago refused to put in generics and closures, an omission that was a big mistake. That Go chose not to have generics is also baffling to me. The failure of many languages to have a proper module system (including Haskell, Java, and Go) is also one of those things that has caused headaches and will continue to be a pain point. And we've seen how C++11 (and C++14 coming up) have been truly crippled by not biting the bullet earlier in design. It's great that Go has in fact started from a cleaner slate than C and C++, it being over 30 years later than them, of course.

AreaMan

The Go Authors say they haven't ruled out generics, but don't like any of the implementations that they've seen. Code bloat, ugly syntax, complexity... I tend to agree.

Generics are a win for algorithms and containers. Everywhere else their just a choice among many. Looking at the way Go does sorting and priority queues, I think the current solution is functional and adequate. Giving enough time to think of something better. Once a feature is added to a language, we're stuck with it.

I can think of 2 kinds of generics: A macro/generator system like C++, or a variant data type, which I guess is the same as a union type. The first is compile-time, the second is also run-time. Is there a third or fourth option?

Go packages seem like a module system, but maybe I just don't understand your meaning.

paper writing service reviewsView on Disqus ↗

This Go programming language is actually one of the best tools that a person could consider to use their works in programming especially that it give unique features that can surely make you appreciate the things that you have done after.