Why is it not possible to add an integer to a "dereferenced" pointer variable in Go? - pointers

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

Related

Delphi Records - creating a pointer to it

I'm trying to see how I can create a pointer to a simple record.
I have searched for similar topics before posting but it's quite confusing.
I create A & B of which are actual Records.
I then have a variable C which I want to be just a 'pointer to this record'.
I don't want C to store its own value but just a pointer to either A or B.
But whenever C is read/written to,
it's actually being written to either A or B, whichever C is pointing to.
In other words, it's like a pointer to an Object, but I don't need an Object in my case.
Using Delphi 10.3 & 10.4 (if there's any difference), please highlight.
The code below results in Access Violation on first ShowMessage.
procedure TForm1.Button2Click(Sender: TObject);
type
TMyRecord = record
Field1 : integer;
end;
var
A : TMyRecord;
B : TMyRecord;
C : ^TMyRecord; // how to declare this as a pointer?
begin
A.Field1 := 1;
B.Field1 := 2;
C^ := A; // psuedo code to point to A
A.Field1 := 3;
showmessage( C^.Field1.ToString ); // result is 3
C.Field1 := 4;
showmessage( A.Field1.ToString ); // result is 4
C^ := B; // psuedo code to point to A
C.Field1 := 5;
showmessage( B.Field1.ToString ); // result is 5
// anything to free here to avoid memory loss?
end;
C should contain address of A, so make
C := #A;
and the rest of code will work as needed.
Also note that C.Field1 is implicit dereference, it really works as C^.Field1
For now
C^ := A;
denotes assigning contents of A record to memory region addressed by C, but this memory is not allocated - that's why access violation occurs. (To allocate memory, you can make New(C), but this is not needed for your purposes)
Also if you are going to actively use pointer to record, you can define type
PMyRecord = ^TMyRecord;

Tour of Go, difference between & and no & when referring to a Vector struct

I know using & symbol address the address of the stored value, but as I'm going the "Tour of Go", in the sections where they introducing pointers and special receivers, they have code as follow for referring to a Vector struct to scale and get the absolute value as shown:
package main
import (
"fmt"
"math"
)
type Vertex struct {
X, Y float64
}
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := &Vertex{3, 4}
fmt.Printf("Before scaling: %+v, Abs: %v\n", v, v.Abs())
v.Scale(5)
fmt.Printf("After scaling: %+v, Abs: %v\n", v, v.Abs())
}
With an output of:
Before scaling: &{X:3 Y:4}, Abs: 5
After scaling: &{X:15 Y:20}, Abs: 25
But if I change the main function call to have v := Vector{3.4} instead of v:= &Vector{3.4}, I get the same output. Is it better practice to refer to the memeory address in this case? More of a conceptual circumstance I don't seem to understand.
You will not get the exact same output, notice that the output no longer indicates that you've passed a pointer (the & is missing):
Before scaling: {X:3 Y:4}, Abs: 5
After scaling: {X:15 Y:20}, Abs: 25
The reason you can still call the absolute value method is because Go implicitly takes the address of v for you when it sees that the method exists on a pointer type but you've used the struct directly since it is always possible to take the address of the struct and derive a method call on the pointer receiver.
For more information, see the "Method expressions" section of the Go spec: https://golang.org/ref/spec#Method_expressions
There isn't really enough information in this specific instance to tell you whether it's good or bad practice to use the struct value or always pass a pointer around. This is very dependent on the situation, the size of the struct, whether you want your value stack or heap allocated, and any number of other factors. However, for most programs it probably won't make a difference and I'd advise that it's not worth worrying about early on as you learn Go.

Get pointer on var obtained via interface

In the following code
var a int
var b interface{}
b = a
fmt.Printf("%T, %T \n", a, &a)
fmt.Printf("%T, %T \n", b, &b)
output:
int, *int
int, *interface {}
I would expect the type of &b to be a pointer on int.
I have two questions:
1) Why is it a pointer on interface{} ?
2) How could I get a pointer on the original type ?
&b => this is the address operator applied on the variable b, whose type is interface{}. So &b will be a pointer of type *interface{}, pointing to the variable b. If you take the address of a variable of type T, the result will always be of type *T.
You cannot obtain the address of the variable a from b, because the assignment:
b = a
Simply copies the value of a into b. It wraps the value of a in an interface value of type interface{}, and stores this interface value into b. This value is completely detached from a.
In general, all assignments copy the values being assigned. There are no reference types in Go. The closest you can get to what you want is if you store the address of a in b in the first place, e.g.:
b = &a
Then you can use type assertion to get out a's address from b like this:
fmt.Printf("%T, %T \n", a, &a)
fmt.Printf("%T, %T \n", b, b.(*int))
This outputs (try it on the Go Playground):
int, *int
*int, *int
(Note: when you simply print b, since it is of an interface type, the fmt package prints the (concrete) value wrapped in it.)
See related questions:
How to get a pointer to a variable that's masked as an interface?
Changing pointer type and value under interface with reflection
Just to complete icza's answer. In case if you don't know the type of the value stored in the interface (and, hence, you can't explicitly use type assertion), you can use reflect package:
var a int
var b interface{}
b = &a
fmt.Println(reflect.TypeOf(b))

Set an int pointer to an int value in Go

I'm very new to Go and am trying to set a *int to point to a number, say 12345.
package main
import (
"fmt"
"reflect"
)
func main() {
var guess *int
fmt.Println(reflect.TypeOf(guess))
*guess = 12345
fmt.Println(guess)
}
But it's giving me the following error:
Type: *int
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x483c7d]
goroutine 1 [running]:
main.main()
/home/aaron/projects/gopath/src/github.com/AaronNBrock/go-guess/main.go:16 +0x9d
exit status 2
I see that the error is with the *guess = 12345 since 12345, but I'm not sure what's causing it.
You have a pointer variable which after declaration will be nil.
If you want to set the pointed value, it must point to something. Attempting to dereference a nil pointer is a runtime panic, just what you experienced. You may use the builtin new() function to obtain a pointer to a zero-valued int, and then you can set the pointed value:
var guess *int
guess = new(int)
*guess = 12345
Your modified app:
var guess *int
fmt.Println(guess)
guess = new(int)
*guess = 12345
fmt.Println(guess, *guess)
Output (try it on the Go Playground):
<nil>
0x10414028 12345
Note that you can make this shorter using a short variable declaration like this:
guess := new(int)
*guess = 12345
Another option to make a pointer point to something "useful" is to assign the address of a variable to the pointer variable, like this:
value := 12345 // will be of type int
guess := &value
But this solution modifies the pointer value, not the pointed value. The result is the same though in this simple example.
You could also just assign the address of another variable, and then proceed to change the pointed value:
var value int
guess := &value
*guess = 12345
Also note that since guess points to value, changing the pointed value will change the value of the value variable too. Also if you change the value variable directly, the pointed value by guess also changes: they are one and the same:
var value int
guess := &value
value = 12345
fmt.Println(*guess) // This will also print 12345
Try this one on the Go Playground.
FWIW, if you do this often enough (like setting up data in unit tests) it's useful to have a shorthand, hence:
https://github.com/mwielbut/pointy
val := 42
pointerToVal := &val
// vs.
pointerToVal := pointy.Int(42)
Here's one possible utility function:
func getIntPointer(val int) *int {
return &val
}
Or as an inline anonymous function:
func(val int) *int { return &val }(val)
For example,
var foo *int = func(val int) *int { return &val }(10)
Run on The Go Playground
EDIT: It's probably better to make this a 2-liner:
val := new(int)
*val = 5
Assuming you really want an int pointer and not just an int, then you need a variable to store the int you point to. For example:
var guess *int
a := 12345
guess = &a
Starting from Go 1.18 you can make use of generics
func Pointer[K any](val K) *K {
return &val
}
A tricky way to get int pointer without create new variable.
someIntPtr := &[]int64{10}[0]
Like this, you don't have to use a one line func like func(val int) *int { return &val }(10) or create a variable of int.

How does this Go code set the value of an object through a pointer, without dereferencing?

I'm learning Go from a Java/Python background, and am confused by this code from the Go tutorial. In the following code, the line
p.X = 1e9
sets the value of v.X to 1e9 using pointer p. As p is merely a pointer to v, isn't dereferencing necessary to set v's value? Thus the correct statement would be:
*p.X = 1e9
Naturally, this results in an error. Can someone explain why the Go example code works as it is?
Code in question:
package main
import (
"fmt"
)
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
p := &v
p.X = 1e9
fmt.Println(v)
}
In go, the compiler automatically converts the expression to (*p).X. From the the language spec:
if the type of x is a named pointer type and (*x).f is a valid
selector expression denoting a field (but not a method), x.f is
shorthand for (*x).f.

Resources