Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does pointer dereferencing work in Go?

Tags:

pointers

go

I'm going through the golang tutorials at http://tour.golang.org/, and was experimenting a bit with some things in example 29

For your reference, the original example is copied here:

package main  import "fmt"  type Vertex struct {     X, Y int }  var (     p = Vertex{1, 2}  // has type Vertex     q = &Vertex{1, 2} // has type *Vertex     r = Vertex{X: 1}  // Y:0 is implicit     s = Vertex{}      // X:0 and Y:0 )  func main() {     fmt.Println(p, q, r, s) } 

It's pretty basic, showing how to create instances of this fancy new struct, Vertex. Example 28, though, shows manipulating a vertex via a pointer to it, so I modified the example a bit and was surprised by the output. Here is the modification:

func main() {     t := *q     q.X = 4     u := *q     fmt.Println(p, q, r, s, t, u, t == u) } 

And the output:

{1 2} &{4 2} {1 0} {0 0} {1 2} {4 2} false 

The thing that surprised me is that t is not {4, 2}, which seems to mean that changing q.X changed the instance of the struct that q pointed to. Coming from a C/C++ background, this seems like extremely strange behavior to me.

So, what's actually going on here? Why does using q.X = 4 to change the Vertex not propagate to t?

like image 375
Kevin Avatar asked Nov 23 '14 01:11

Kevin


People also ask

How do I dereference a pointer in Go?

Pointers can be dereferenced by adding an asterisk * before a pointer.

How does pointer work in Golang?

Pointers in Go programming language or Golang is a variable that is used to store the memory address of another variable. Pointers in Golang is also termed as the special variables. The variables are used to store some data at a particular memory address in the system.

Does Golang automatically dereference?

Go performs automatic dereferencing for struct data type in its specification. Hence, you do not need to de-reference it explicitly. Quote: As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).

What does dereferencing pointer do?

Dereferencing is used to access or manipulate data contained in memory location pointed to by a pointer. *(asterisk) is used with pointer variable when dereferencing the pointer variable, it refers to variable being pointed, so this is called dereferencing of pointers.


1 Answers

t := *q makes a copy of the struct pointed to by q.

If you want to observe changes to q through t, then stick with a pointer:

var (     p = Vertex{1, 2}  // has type Vertex     q = &Vertex{1, 2} // has type *Vertex     r = Vertex{X: 1}  // Y:0 is implicit     s = Vertex{}      // X:0 and Y:0 )   func main() {     t := q     q.X = 4     u := *q     fmt.Println(p, q, r, s, t, u, *t == u) } 

This produces the output you were probably looking for.

{1 2} &{4 2} {1 0} {0 0} &{4 2} {4 2} true 

I'm not sure what seems extremely strange to you. C and C++ behave the same way. Consider the following:

#include <iostream>  struct Vertex {     int x;     int y; };  std::ostream& operator<<(std::ostream& out, const Vertex& v) {     out << "{ " << v.x << ", " << v.y << " }";      return out; }  int main() {     Vertex v = Vertex{1, 2};     Vertex* q = &v;     Vertex t = *q;     q->x = 4;     std::cout << "*q: " << *q << "\n";     std::cout << " t: " << t << "\n"; } 

The output of this C++ code shows the same behavior:

*q: { 4, 2 }   t: { 1, 2 } 
like image 165
zmb Avatar answered Sep 27 '22 21:09

zmb