1) It's a confusion about the language that leads you to think *x
and &x
are the same type. As Not_a_Golfer pointed out, the uses of *
in expressions and type names are different. *x
in your main()
is invalid syntax, because *
in an expression tries to get the value pointed to by the pointer that follows, but x
is not a pointer (it's an int
).
I think you were thinking of the fact that when you take a pointer to x
using &x
, the character you add to the type name is *
to form *int
. I can see how it's confusing that &var
gets you *typ
rather than &typ
. On the other hand, if they'd put &
on the type name instead, that would be confusing in other situations. Some trickiness is inevitable, and like human languages, it may be easier to learn by using than discussion alone.
2) Again, turns out the assumption is inaccurate: a, b = b, a
swaps the pointers that the swap
function looks at, but doesn't swap the values from main
's perspective and the last line of output changes to 5 15 2
: http://play.golang.org/p/rCXDgkZ9kG
3) swap
is printing the address of the pointer variables, not of the underlying integers. You'd print a
and b
to see the addresses of the integers.
4) I'm going to assume, maybe wrongly, that you were hoping you could swap the locations that arbitrary variables point to with &
syntax, as in &x, &y = &y, &x
, without ever declaring pointer variables. There's some ambiguity, and if that's not what you were going for, I'm not sure if this part of the answer will help you.
As with many "why can't I..." questions the easy out is "because they defined the language that way". But going to why it's that way a little bit, I think you're required to declare a variable as a pointer at some point (or another type implemented using pointers, like maps or slices) because pointers come with booby traps: you can do something over in one piece of code that changes other code's local variables in unexpected ways, for example. So wherever you see *int
appear, it's telling you you might have to worry about (or, that you're able to use) things like nil
pointers, concurrent access from multiple pieces of code, etc.
Go is a bit more conservative about making pointer-hood explicit than other languages are: C++, for example, has the concept of "reference parameters" (int& i
) where you could do your swap(x,y)
with no &
or pointers appearing in main
. In other words, in languages with reference parameters, you might have to look at the declaration of a function to know whether it will change its arguments. That sort of behavior was a little too surprising/implicit/tricky for the Go folks to adopt.
No getting around that all the referencing and dereferencing takes some thinking, and you might just have to work with it a while to get it; hope all this helps, though.