4 ms·
Nice article, thanks for publishing this. However: >This panic is caused by dereferencing a nil pointer, as indicated by the first line of the output. These ty
by obeattie 9y ago
Nice article, thanks for publishing this. However:
>This panic is caused by dereferencing a nil pointer, as indicated by the first line of the output. These types of errors are much less common in Go than in other languages like C or Java thanks to Go’s idioms around error handling.
I often see assertions made like this about Go. My experience at companies which use Go as their primary development language with reasonably-sized teams (30-50 people working on hundreds/thousands of Go programs) does not agree with this. I would say nil pointer dereference errors are just as common as if they were writing code in C or Java. I don't have hard data to back this up though; perhaps you do.
- icholy 9y agoIt happens way more often in java because all references are nullable. In Go, unless you're dealing with a pointer, it's not going to be nil.
- bsaul 9y agoNot a lot of experience in go, but I’d say deadlocks ( yes, even with channels), and nil pointers are indeed the two most common errors i encountered. Go do makes things easier, but not fail proof.
- notheguyouthink 9y agoI think it depends on what you're doing. In my old org, we often avoided pointers. Or rather, we used them when we needed them. Because of this, I'd wager easily 50% of our codebase was not using pointers at all and was completely type safe. Though regardless, after using Rust for a while, i hope we can find a way to bring that safety to Go. I use a compiler and not JS/Python/etc for a reason, after all. I want compile time safety, all the time.
- LaFolle 9y agoOne of the most common errors that i used to encounter when i first started with golang was- accessing a map without initializing it first. For example: var m map[string]int m["name"] = 23 which resulted in "panic: assignment to entry in nil map". Nil pointer access errors are relatively easy to debug when in Go world, as compared to in CGO. Like, we are using zmq via CGO in one of our project and when these errors occured, we had to use gdb to debug (apart from logging). At one time we even used rr. rr is really cool, everyone should check this out. https://github.com/mozilla/rr https://github.com/mozilla/rr
- masklinn 9y agoI really fail to see how "Go's idioms around error handling" would make NPE rarer than in Java either. In java, an error is an exception and will bubble up to the handler, it has very little reason to "birth" null references. In Go, an error is a non-nil value next to a zero (often nil) value, and a success is the reverse, so error handling always injects new nils which you're supposed to carefully not used (since no sum types).
- joeshaw 9y agoMy explanation for why is the following sentence: > If a function could fail, the function must return an error as its last return value. The caller should immediately check for errors from that function. In practice, in idiomatic code it is quite rare for a function that returns a `(* Something, error)` to return `(nil, nil)`, which are the cases where a nil pointer dereference would most often happen. The other case is not _immediately_ checking errors. I would say both of these cases are not idiomatic Go. (Yes, there are exceptions.) The other cases where I've seen nil dereferences pop up most often: (1) the zero value for maps is nil, and a nil map is mostly not usable. `m[50] = "foo"` will panic with a nil dereference if you've not initialized `m`. This is one of the most annoying things about Go. (2) not checking for presence when pulling out of a map. If you have `map[string]* Something` and do `x := m["nonexistent"]` and try to use `x`, it'll blow up. Always use the `x, ok := m["nonexistent"]` form instead, and deal with stuff when `ok == false`. (3) nil receivers. `var x *Something`, then `x.Method()` -- the `Method()` method _can_ deal when `x == nil`, but most code does not. My reasons for citing C and Java: C doesn't have multiple return values, and kinds of C code deals with errors differently. Lots of stuff just returns `NULL` and all too often things don't check for it. (`malloc()` is a perfect example of this -- it rarely fails but a _lot_ of code doesn't check for errors. Now extrapolate that to everything :) For Java, it's because the try-catch control structure complicates program flow. If you have a large block of code in a try-catch, it is very easy for a different line of code to throw an exception than you expected, and as a result an object you attempt to dereference later is null and you get an NPE. There are ways to deal with this, of course, but in my experience most people are pretty lazy about the non-happy path. EDIT: formatting. how can a site about programming have such terrible support for typing in code
- NateDad 9y agoMy 7 years of C++ and 7 yesterday of C# and 5 years of go agree with you. Many more nil pointer exceptions in the former and almost none in the later in similar size (large) codebases.
- weberc2 9y agoMy 6 years of C++ and 8 years of C# and 10 years of Java and 5 years of Go agree with you both.
- weberc2 9y agoMy experience is that it's slightly less common in Go than in C or Java, but quite a lot easier to debug than either of the other two. My explanation for why it's less common in Go is that fewer things are pointers, especially compared to Java, and that the things that the cause is more immediately apparent, especially compared to C. Of course, nil/null is still an unnecessary problem in all of these languages, in the sense that there are language features that render these problems obsolete; however, these languages (especially C and Java) aren't likely to adopt these features or at least not to adopt them and completely sunset nil/null for compatibility reasons.