Pointer in Go

A pointer in Go or pointer points to the memory address at which a value is saved. To output the memory address for a variable, use the & character:

1
2
3
4
5
6
7
8
func main() {
	x := 10
	fmt.Println(x)
	fmt.Println(&x)
	
	fmt.Printf("%T\n", x)
	fmt.Printf("%T\n", &x)
}

If you enter the type of the memory address, it is \int. Since \ is the operator for a pointer, that is, the memory address is a pointer to an int. In other words, the pointer points to a memory address at which a value of the type int is stored.

You have to make it clear here that a pointer to an int is a separate type and is not to be equated with the type int.

1
2
3
4
5
6
7
func main() {
	x := 10
	
	y := &x
	fmt.Println(y)
	fmt.Println(y)
}

The operator \ is used in line 6. This dereferences the memory address stored in y i.e. it outputs the value stored there.

1
2
3
4
5
6
7
func main() {
	x := 10
	
	y := &x
	y = 88
	fmt.Println(x)
}

Here x =c88 is set. This is because the variable y contains the memory address of x. By using \ y = 88 dereferencing happens again, i.e. the program is basically told “set the value at the address stored in y equal to 88”.

How Pointers Are Used

Pointers are particularly useful when you want to transfer large amounts of data. It is much more efficient to refer to the address where the data is stored than to pass the data on to yourself.

The second use case is that you sometimes want to change values at an address.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func main() {
	var x int = 5
	fmt.Println("Adresse of x", &x)
	numbers(&x)
}

func numbers(x int) {
	fmt.Println("x before ",x)
	fmt.Println("Adresse of x", &x)
	x = 48
	fmt.Println("x after ",x)
	fmt.Println("Adresse of x", &x)
}

The function numbers () consumes a pointer of the type int, i.e. we pass the memory address of x in line 3 by passing &x. In the example above, the memory address always remains the same as we change the value at the address.

The numbers() function has no access to. Even if x were passed directly to them, it would not be possible to change x, since a copy of x is created when passed to the function.

Method Set

A method set are the methods that are assigned to a certain data type. A set of methods determines the interfaces that the respective type implements.

There is an important difference in the method sets when receiving arguments:

A receiver that is not defined as a pointer works with pointers and also with non-pointers.

A receiver that is defined as a pointer only works with pointers.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import (
	"fmt"
	"math"
)

type circle struct {
	radius float64
}

type shape interface {
	area() float64
}

func (c circle) area() float64 {
	return math.Pi  c.radius  c.radius
}

func info(f shape) {
	fmt.Println("Area", f.area())
}

func main() {
	k := circle{5}
	info(&k)  //Pointer 
	info(k)   //Non-pointer
}

The calls in lines 26 and 27 both lead to the same result. If the method area() were to be defined differently, the call in line 27 would cause an error:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
...
func (c circle) area() float64 {
	return math.Pi  c.radius  c.radius
}
...

func main() {
	k := circle{5}
	info(&k)  //Pointer 
	info(k)   //Non-pointer = ERROR
}

The reason why info(k) fails is that the function specifically requests a pointer of the type circle. Since, as already described above, a \circle type pointer is an independent type and not the same as the circle type, a pointer must also be passed here.

0%