News for hackers. Stuff that matters.
Re:Understand Go pointers by nottorp on Wednesday April 26, 2017 @09:14AM (#14202639)
I clicked the article thinking that Go pointers are something special... but this seems targeted at the "programmers" who only know javascript...
Re:Understand Go pointers by jerf on Wednesday April 26, 2017 @09:46AM (#14202857)
Since you sort of ask: Go pointers themselves are not that special, because in a GC'ed language with no pointer arithmetic they're really just a map/territory-type distinction, but there are some syntax affordances that can make them briefly more confusing than they appear.

For method calls and field accesses, Go fuzzes whether you have an object or a pointer by making the "." operator work on both, rather than C's "." vs "->" distinction. Since it's never ambiguous, it's just pointless overhead to make the programmer worry about that. It can also be slightly confusing that the method itself can control whether it receives a pointer, so you can call object.Method on a concrete object, but Method will receive &object. As a professional programmer I appreciate not being bothered with this unambiguous detail that the language can easily handle for me, but it can confuse people in the early going, which is a legitimate criticism. (I still come down in favor of doing what it is doing, but it is a legitimate drawback.)

The other thing I see that fools people with experience from other languages is that the "nil" pointer is not the same thing as a NULL pointer in C. In C, the NULL pointer is simply a zero with no type information connected to it. In Go, pointers are actually (type, address) tuples, so a nil pointer to a custom struct is actually (pointer CustomStruct [1], nil), which means that the runtime is capable of correctly resolving methods on nil pointers and that you can therefore write methods that work on nil pointers. Nil pointers are still bad because they are a value added to all pointer types by the act of taking a pointer that you can't control, you get it whether you like it or not, but they are not bad in the C sense that any attempt to touch one is a segfault.[2]

That's about all that matters in normal Go programming.

[1]: Asterisk is confusing HN's italicization there.

[2]: Which is I think an important aspect of understanding the "billion dollar mistake", by the way; it is easy to deconstruct that mistake as being two mistakes rolled in to one, which may perhaps explain why it was such a big mistake.

Re:Understand Go pointers by dbaupp on Wednesday April 26, 2017 @01:00PM (#14204808)
> The other thing I see that fools people with experience from other languages is that the "nil" pointer is not the same thing as a NULL pointer in C. In C, the NULL pointer is simply a zero with no type information connected to it. In Go, pointers are actually (type, address) tuples, so a nil pointer to a custom struct is actually (pointer CustomStruct [1], nil), which means that the runtime is capable of correctly resolving methods on nil pointers and that you can therefore write methods that work on nil pointers.

This paragraph seems, at best, misleading. C NULLs are not untyped either (using the same asterisk-avoidance as you): `T pointer x = NULL` means x is a NULL pointer with type T. Similarly, a Go `var x pointer T = nil` is a plain pointer-sized object with all bytes zero, just like C.

If you're talking about interfaces, then, there's actually two sorts of nil interfaces: interfaces where the data pointer is nil, and interfaces that are completely nil (both data and type/interface-info pointers).

  func main() {
  	var x *int
  	var y interface{} = x
  	var z interface{}
  	fmt.Printf("%v, %v, %T, %v, %T, %v", x, y, y, z, z, y == z)	
  	// <nil>, <nil>, *int, <nil>, <nil>, false
  }
In any case, for a comparison to C, Go is fairly similar: you can call functions with nil pointers in either, just fine, and dereferencing one is bad (the badness is far more controlled in Go, but see below). For a more reasonable comparison about methods, C++ could make it legal to call methods on nil/NULL pointers, and, like a completely-nil interface, crash when calling a virtual method (i.e. one that requires dereferencing a nil pointer to get the function pointer), but optimisations win out.

> they are not bad in the C sense that any attempt to touch one is a segfault

Note that this has nothing to do with nil pointers storing runtime types (even if they stored them) or anything like that: the Go language just (sensibly) decided to not have undefined behaviour with nil pointers, requiring that implementations handle them in a reliable/reproducible way.

Re:Understand Go pointers by int_19h on Wednesday April 26, 2017 @10:19PM (#14208723)
> This paragraph seems, at best, misleading. C NULLs are not untyped either (using the same asterisk-avoidance as you): `T pointer x = NULL` means x is a NULL pointer with type T.

The point, I think, is that this type information is carried only at compile time on the binding, not at runtime on the value itself. If you have multiple aliases to the same null value (e.g. via references or pointers to pointers), the behavior will change depending on which alias is used. Not so in Go.

Of course, this is also true for non-null values in C++, when methods are non-virtual, so...

Re:Understand Go pointers by dbaupp on Thursday April 27, 2017 @01:54AM (#14209469)
The rest of my comment fairly specifically covered that: Go nil pointers don't have runtime types (like C), Go nil interfaces sometimes do.

In any case, pointers to pointers with different types seem likely to be a strict aliasing violation in C.

Re:Understand Go pointers by int_19h on Thursday April 27, 2017 @05:39AM (#14210287)
> In any case, pointers to pointers with different types seem likely to be a strict aliasing violation in C.

Surprisingly, no, at least not in similar context. For example, it's perfectly legal to cast a pointer to a struct to a pointer to its first member - it's specifically guaranteed that this works as you'd expect. This is often used when emulating single-inheritance OOP in C - your "base class" is then the first member of struct type, and this lets you upcast and downcast with impunity.

Re:Understand Go pointers by dbaupp on Thursday April 27, 2017 @12:15PM (#14212640)
Casting pointer-to-struct to pointer-to-field is fine, yes, but is it legal to cast pointer-to-pointer-to-struct to pointer-to-pointer-to-field? (I genuinely don't know the answer to this.) The former results in a new (temporary or otherwise) value with a new static static type, independent of the original, while the latter does not, and so is the interesting one. In any case, note that Go also has something a little similar, with its anonymous fields approach to composition.

However, that's not still at all the main point: there's actually not that much difference between how C and Go behave with compiletime/runtime types.

Re:Understand Go pointers by int_19h on Thursday April 27, 2017 @06:47PM (#14215467)
To the best of my language lawyering knowledge, no, such a cast wouldn't be legal, and would indeed be a strict aliasing violation.
Re:Understand Go pointers by pcwalton on Wednesday April 26, 2017 @10:02AM (#14202996)
> Which is I think an important aspect of understanding the "billion dollar mistake", by the way; it is easy to deconstruct that mistake as being two mistakes rolled in to one, which may perhaps explain why it was such a big mistake.

If it's two mistakes, it's one big one (having null pointers at all) and one tiny one (the fact that calling methods on null pointers is undefined behavior in C++). The latter is yet another C++ gotcha, but not nearly as pernicious as the former, which causes nearly all the null pointer-related bugs in the wild.

Re:Understand Go pointers by jerf on Wednesday April 26, 2017 @10:14AM (#14203107)
Yes, I agree that adding values that you can not avoid having into the set of valid values for a type is the worse one by quite a bit.

However, I'm still not a big fan of languages where values exist that are automatically crashes if you try to touch them in some bad way. Why are they there, then? My mental image is one of the anthropomorphized language just tossing caltrops around willy-nilly and blaming people who get stabbed for not being careful where they walk. I think it's important to call this idea out separately because programmers should learn this principle as they learn how to use strong typing systems: Do your best to exclude meaningless states for which your only recourse will be to crash if you see one from your system at the type level. The C-style NULL value is a degenerate case of this general principle.

Yes, this absolutely includes Go. I consider it a mistake in any language. In particular I'd highlight the distinction between reading a nil map (legal, gets the zero value of the value type for the map) and writing to one ("kablooie") as particularly bothersome and asymmetric, especially in light of the way nil slices can often be "written" to (via append which is in practice much more common than using index access to write) legally. Lots of asymmetries around what actually blows up vs. what "works" (but quite likely isn't doing what you want) in Go here. I'm not really in love with getting zero values out of a map if the key doesn't exist anyhow and I tend to pretend that only the check for both the value and existence exists in my own code (because I almost always care about existence too), but I especially don't like that behavior out of nil maps.

Re:Understand Go pointers by GuB-42 on Wednesday April 26, 2017 @01:38PM (#14205176)
Undefined behavior is what makes C efficient. And NULL pointers are just a consequence of the ability of pointers to take numerical values. Naturally, this behavior was kept in C++, which is just a superset of C (with a few minor exceptions).

NULL pointers and undefined behavior make a lot of sense in C++. The mistake is replicating this behavior on languages where it doesn't.

Re:Understand Go pointers by int_19h on Wednesday April 26, 2017 @10:25PM (#14208742)
> And NULL pointers are just a consequence of the ability of pointers to take numerical values.

Not at all. The C standard doesn't allow pointers to take arbitrary numerical values; while you can cast back and forth, the only guarantee is that casting a pointer to a numeric value and back to a pointer still points to the original object (and even then only if the numeric type used is large enough, which couldn't be portably ensured prior to C99, and is only conditionally supported even now).

In particular, one thing that the standard does not guarantee - and there have been implementations that did not do so - is that casting a null pointer to int will produce zero, or that casting int zero to a pointer will produce null. Nor does it guarantee that a null pointer is an all-bits-zero value.

The fact that you can write "p = 0" in C is not because pointers can take arbitrary numerical values, but because the language syntax and semantics allow you to do so, with 0 being treated specially when assigned to an lvalue of a pointer type. But you can't write "p = 1", for example, because there's no such special treatment for any other integer literal.

Re:Understand Go pointers by shanemhansen on Wednesday April 26, 2017 @03:14PM (#14206052)
> In Go, pointers are actually (type, address) tuples, so a nil pointer to a custom struct is actually (pointer CustomStruct [1], nil)

I could be wrong but I think that's not right. The key difference is dynamic vs static dispatch. What you're describing (type, address) is how go represents interfaces. So go can resolve a.Read() on an io.Reader if the value is (os.File, nil). A go empty interface is not like a c void pointer for that reason. Type info is preserved and can be safely recovered.

But go also has non-virtual method calls unlike Java (afaik), it doesn't implicitly dynamic dispatch. This is a consequence of the fact that it doesn't have inheritance. If you write var foo os.File; foo.Close(); there's no runtime (type,address) tuple. That .Close() call is essentially compiled directly to something like CALL os.File.Close(nil). This can potentially be inlined even. If your method treats nil specially that's up to you.

Re:Understand Go pointers by zzzcpan on Wednesday April 26, 2017 @10:50AM (#14203425)
"it's just pointless overhead to make the programmer worry about that"

You are incorrect, removing this distinction actually adds overhead of keeping a type in mind when reading and working with code. And overall selector operator in Go is pretty bad, no need to defend it, it forces you to always keep in mind some things, like not to collide with a namespace, because there is no :: operator for namespaces and always look around where the thing is defined, because it's not obvious whether it's a namespace, an interface, a struct or a pointer receiver.

Re:Understand Go pointers by pjmlp on Wednesday April 26, 2017 @11:04AM (#14203554)
Go has pointer arithmetic via the unsafe package, it just makes it very explicit, as it should be.
Re:Understand Go pointers by lclarkmichalek on Wednesday April 26, 2017 @09:24AM (#14202715)
Programmers who only know javascript are, controversially, still programmers.
Re:Understand Go pointers by bpp on Wednesday April 26, 2017 @10:12AM (#14203090)
I'm a programmer who spends all day in Go working on backend systems, but came to it from Javascript, my first language. Pointers were one of the concepts that took me the longest to understand, even having dug into them previously in the context of V8's object implementation. So I for one am grateful for this article, and just passed it on to a recent bootcamp grad at my company. Hopefully it will accelerate his learning curve.
Re:Understand Go pointers by penpapersw on Wednesday April 26, 2017 @10:38AM (#14203331)
The first language I learned was QBasic, so when I started to learn C++, the concept of pointers was bizarre and took longer to learn than it should have, but after it finally clicked, it gave me a special love for pointers, the simplicity of C, and low-level programming in general.
Re:Understand Go pointers by int_19h on Wednesday April 26, 2017 @10:57PM (#14208843)
While QBasic didn't have pointer types, it did have pointers in disguise (or rather, pointers without disguise, which are just memory addresses) - VARPTR, PEEK and POKE. As I recall, PEEK'ing and POKE'ing things was actually necessary to do many important tricks in QB, especially once you started playing with CALL INTERRUPT.
Re:Understand Go pointers by EdiX on Wednesday April 26, 2017 @09:48AM (#14202878)
Regardless of whether they can be called programmers, we can not deny that they exist.
Re:Understand Go pointers by leshow on Wednesday April 26, 2017 @09:40AM (#14202818)
Even if you're a JS programmer, having no knowledge of pointers just shows you've never dug very deep into how your language works. Does JS pass by value? by reference? does it pass references by value? These are all things a JS programmer should know, and requires some knowledge of pointers.
Re:Understand Go pointers by bsaul on Wednesday April 26, 2017 @04:15PM (#14206546)
Don't understand the downvote. Understanding javascript's closure (which is a core js feature even on the client) properly without understanding pointers seems like an impossible task to me.
Re:Understand Go pointers by inimino on Thursday April 27, 2017 @08:48AM (#14211013)
The idea of reference is necessary, but pointers are an implementation detail. If you don't come from C, you can understand everything in JavaScript without knowing what pointers are. Many languages have references to mutable state without the peculiar details that make pointers what they are.
Re:Understand Go pointers by akuji1993 on Wednesday April 26, 2017 @10:05AM (#14203034)
I'm really tired of people bashing Javascript to death. It's here, it's being used, wether you like it or not. Stop whining about it, please.
Re:Understand Go pointers by TeMPOraL on Wednesday April 26, 2017 @12:44PM (#14204649)
The constructive question here is: is there any way to make JavaScript stop being used (especially for tasks not related to webpages)?
Re:Understand Go pointers by self-diversity on Wednesday April 26, 2017 @04:13PM (#14206532)
Nope. Especially since many of us don't have piles of irrational hatred for it.
Re:Understand Go pointers by inimino on Thursday April 27, 2017 @08:49AM (#14211017)
That is not a constructive question.
Re:Understand Go pointers by weberc2 on Wednesday April 26, 2017 @10:17AM (#14203138)
Or Python or Java or C# or any other language without pointers... These languages command a huge marketshare.

This article is clearly targeting folks coming to Go from those languages.

Re:Understand Go pointers by DrJokepu on Wednesday April 26, 2017 @10:28AM (#14203243)
C# actually has (unsafe) pointers, although they're not used (and are not intended to be used) very frequently.
Re:Understand Go pointers by aaron-lebo on Wednesday April 26, 2017 @09:25AM (#14202720)
Yes, there are programmers who only know JS.

There's nothing "wrong" with that. If you only work in Ruby, Python, JS, or even functional languages it's very possible you've never run across pointers (at least not explicitly).

It's actually something people misunderstand about C, it's fundamentally a memory-oriented language in a way functional or OO languages are not and there are some real advantages to working that way. Ironically, this actually shows through in JS with the constructs you use to manipulate arrays (cause it borrowed from C).

No need to look down on other programmers; we all gotta start somewhere.

Re:Understand Go pointers by nottorp on Wednesday April 26, 2017 @09:28AM (#14202737)
We all do... but IMO it's better to start with BASIC than Javascript...
Re:Understand Go pointers by jerf on Wednesday April 26, 2017 @09:49AM (#14202885)
BASIC is an ill-defined term, but if you mean the most modern versions of BASIC (as I seriously hope you don't mean 8-bit era BASIC), they aren't significantly different from Javascript circa 2005 in terms of quirkiness and silliness (and that's assuming you've got one with some sort of closure support, which I don't recall if one ever existed; without that BASIC is a clear loser behind Javascript-2005), and Javascript is certainly moving to exceed any BASIC I know about lately.

Javascript does have a lot of flaws, but unlike BASIC which is pretty much dead, the main structure of Javascript is alive and well, as dynamic scripting languages are still very much a going concern.

Re:Understand Go pointers by pjmlp on Wednesday April 26, 2017 @10:59AM (#14203520)
> BASIC which is pretty much dead

Tell that to the enterprise employees writing Office macros or doing VB.NET applications.