Coming from Python, I'm currently learning Go and trying to wrap my head around pointers.
I've written this code in order to understand the concept:
a := 1
b := &a
fmt.Println(b) // Shows the memory address of a
fmt.Println(*b) // Shows the value 1
*b++
fmt.Println(a) // Shows the value 2 (as expected)
I tried to play around with this code to improve my understanding. The following, however, does not work:
a := 1
b := &a
fmt.Println(b) // Shows the memory address of a
fmt.Println(*b) // Shows the value 1
b = *b + 1 // Compile error: invalid operation: b * +1 (mismatched types *int and int)
fmt.Println(a)
Apparently, *b
is of type *int
, while the value 1
is (obviously) of type int
. However, why is it possible to increment the value of a with *b++
in the first example?
From the beginning:
b := &a
Here, b
is of type *int
, a pointer to a location in memory where value of a
is stored. When you do *b
, you are accessing a value from the location b
pointer points to.
When you do *b++
, it stands for *b = *b + 1
and you are incrementing a value on the location b
pointer points to.
b = *b + 1
is invalid because you are trying to add *b
and 1
, which are both type of int
, to b
, which is a pointer (type of *int
).
Why is it not possible to add an integer to a “dereferenced” pointer variable in Go?
b
is a pointer and dereferenced b
is written as *b
. b = *b + 1
is invalid because you're trying to convert an integer to a pointer, which is not possible even when explicitly typecasted. You'll need to instead modify the data that pointer is pointing to, not the pointer itself: *b = *b + 1
.
Take a look at the Go spec here regarding why *b++
works: https://golang.org/ref/spec
Operator precedence
Unary operators have the highest precedence. As the ++ and -- operators form statements, not expressions, they fall outside the operator hierarchy. As a consequence, statement *p++ is the same as (*p)++.
Adding an integer to a dereferenced (integer) pointer variable is possible and is working in your case correctly. However, assigning this value to a pointer variable is not acceptable in Go for type safety reasons. And it is normally not needed (but there is a way to reference any given address though). Hope this clarifies it.
You are adding a *int
to an int
. Hence, the error. As b is a pointer to an integer, to do anything with that integer(read or write), you need to de-reference it. Below code will work as expected. That's what *b++
does internally.
package main
import (
"fmt"
)
func main() {
a := 1
b := &a
fmt.Println(b) // Shows the memory address of a
fmt.Println(*b) // Shows the value 1
*b = *b + 1 // No Compile error
fmt.Println(a) // Shows the value 2
}
Try it here: https://play.golang.org/p/2RX1CWD-AQC