Go - Pointers



Pointers in Go are easy and fun to learn. Some Go programming tasks are performed more easily with pointers, and other tasks, such as call by reference, cannot be performed without using pointers. So it becomes necessary to learn pointers to become a perfect Go programmer.

As you know, every variable is a memory location and every memory location has its address defined which can be accessed using ampersand (&) operator, which denotes an address in memory. Consider the following example, which will print the address of the variables defined −

 package main import "fmt" func main() { var a int = 10 fmt.Printf("Address of a variable: %x\n", &a ) } 

When the above code is compiled and executed, it produces the following result −

 Address of a variable: 10328000 

So you understood what is memory address and how to access it. Now let us see what pointers are.

What Are Pointers?

A pointer is a variable whose value is the address of another variable, i.e., direct address of the memory location. Like any variable or constant, you must declare a pointer before you can use it to store any variable address. The general form of a pointer variable declaration is −

 var var_name *var-type 

Here, type is the pointer's base type; it must be a valid C data type and var-name is the name of the pointer variable. The asterisk * you used to declare a pointer is the same asterisk that you use for multiplication. However, in this statement the asterisk is being used to designate a variable as a pointer. Following are the valid pointer declaration −

 var ip *int /* pointer to an integer */ var fp *float32 /* pointer to a float */ 

The actual data type of the value of all pointers, whether integer, float, or otherwise, is the same, a long hexadecimal number that represents a memory address. The only difference between pointers of different data types is the data type of the variable or constant that the pointer points to.

How to Use Pointers?

There are a few important operations, which we frequently perform with pointers: (a) we define pointer variables, (b) assign the address of a variable to a pointer, and (c) access the value at the address stored in the pointer variable.

All these operations are carried out using the unary operator * that returns the value of the variable located at the address specified by its operand. The following example demonstrates how to perform these operations −

 package main import "fmt" func main() { var a int = 20 /* actual variable declaration */ var ip *int /* pointer variable declaration */ ip = &a /* store address of a in pointer variable*/ fmt.Printf("Address of a variable: %x\n", &a ) /* address stored in pointer variable */ fmt.Printf("Address stored in ip variable: %x\n", ip ) /* access the value using the pointer */ fmt.Printf("Value of *ip variable: %d\n", *ip ) } 

When the above code is compiled and executed, it produces the following result −

 Address of var variable: 10328000 Address stored in ip variable: 10328000 Value of *ip variable: 20 

Nil Pointers in Go

Go compiler assign a Nil value to a pointer variable in case you do not have exact address to be assigned. This is done at the time of variable declaration. A pointer that is assigned nil is called a nil pointer.

The nil pointer is a constant with a value of zero defined in several standard libraries. Consider the following program −

 package main import "fmt" func main() { var ptr *int fmt.Printf("The value of ptr is : %x\n", ptr ) } 

When the above code is compiled and executed, it produces the following result −

 The value of ptr is 0 

On most of the operating systems, programs are not permitted to access memory at address 0 because that memory is reserved by the operating system. However, the memory address 0 has special significance; it signals that the pointer is not intended to point to an accessible memory location. But by convention, if a pointer contains the nil (zero) value, it is assumed to point to nothing.

 if(ptr != nil) /* succeeds if p is not nil */ if(ptr == nil) /* succeeds if p is null */ 

Dereference Pointer in Golang

In Golang, the dereference operator is used to access and manipulate the value stored in the variable pointed to by the pointer. The dereference or indirection operator (*) acts as a unary operator, and it needs a pointer variable as its operand.

The Pointers themselves do not have parameters or return values, but functions that use pointers can have parameters and return values involving pointers.

Syntax

Below is the syntax to dereference a pointer −

 *pointer_variable; 

Using the above syntax, we can get and update the value of any variable that is being pointed to by the pointer.

How to Dereference a Pointer?

To dereference a pointer, we need to follow the below-given steps:

Step 1: Create a variable and declare a pointer variable.

 var x int var ptr *int 

Step 2: Initialize the pointer by assigning the address of the variable.

 x = 10 ptr = &x 

Step 3: Now, we can dereference the pointer to get or update the value of the variable.

 *ptr = 20 fmt.Println(x) value := *ptr fmt.Println(value) 

Example

In this example, we are demonstrating these three steps to deference a pointer −

 package main import "fmt" func main() { x := 10 var ptr *int ptr = &x *ptr = 20 fmt.Printf("Value of x = %d\n", x) value := *ptr fmt.Printf("Value at the address pointed to by ptr = %d\n", value) } 

Output

Run the code and check its output −

 Value of x = 20 Value at the address pointed to by ptr = 20 

What is Dereferencing?

The term "dereferencing" refers to accessing the value that is stored in the memory address referred by the pointer. The dereference operator fetches the value of the target variable.

Example

In this example, we use pointers to store the addresses and values of variables and dereferencing pointers to access their values.

 package main import "fmt" func main() { x := 10 p1 := &x y := 10.5 p2 := &y fmt.Printf("Address of 'x': %p, Value of 'x': %d\n", p1, *p1) fmt.Printf("Address of 'y': %p, Value of 'y': %f\n", p2, *p2) } 

Output

Run the code and check its output −

 Address of 'x': 0xc000110010, Value of 'x': 10 Address of 'y': 0xc000110018, Value of 'y': 10.500000 

Manipulating Value by Dereferencing Pointer

The dereference operator allows indirect manipulation of the value of a variable that refers to a pointer.

Example

In this example, we declare an integer variable x and a pointer p that stores the memory address of x. By dereferencing the pointer p, we can access the value of x. So, we can modify the value of x by changing the value stored at the memory address pointed to by p.

 package main import "fmt" func main() { var x int = 64 var p *int p = &x fmt.Println("Value of x=", x) fmt.Println("Address of x=", &x) fmt.Println("Value of p=", p) fmt.Println("Dereferenced value of p=", *p) *p = 21 fmt.Println("New value of x=", x) } 

Output

Following is the output of the above program

 Value of x= 64 Address of x= 0xc000124010 Value of p= 0xc000124010 Dereferenced value of p= 64 New value of x= 21 

Dereferencing Structure Pointer

In programming, a struct (short for "structure") is a user-defined data type that allows you to group related data together. It is a composite data type that means it can hold multiple values of different data types.

We can define a struct using the type keyword, followed by the name of the struct and the struct keyword.

In Golang, we use the * operator to dereference a pointer to access the struct's fields, or we can use the shorthand notation with the dot operator (.). Unlike C/C++ ,there is no arrow symbol (->) in Go.

Let's have a clear idea how to access struct fields in Golang −

Using the dereference operator

 (*ptr).Name = "Indu" 

Using the shorthand notation

 ptr.Name = "Indu" 

Example

In this example, we create a pointer to a 'Student' struct instance and prints the student's name and age using both direct pointer access and dereferencing.

 package main import "fmt" type Student struct { name string age int } func main() { p := &Student{"Indu", 18} fmt.Println("Name=", p.name) fmt.Println("Age=", (*p).age) } 

Output

Following is the output of the above program

 Name= Indu Age= 18 

Dereferencing Pointers in Functions

Dereferencing pointers in functions involves accessing and modifying the value stored at the memory address pointing to a pointer.

When you pass a pointer to a function, the function can dereference the pointer to access and manipulate the actual value stored at that memory address. This allows the function to modify the original variable's value.

Declaring a pointer

 var FuncPtr func(parameterType) returnType 

Referencing a pointer

 FuncPtr = functionName 

Calling and dereferencing a pointer

 x := FuncPtr(parameter) 

Example

 package main import "fmt" func add(a int, b int) int { return a + b } func main() { var FuncPtr func(int, int) int FuncPtr = add result := FuncPtr(46, 64) fmt.Println("Result=", result) } 

Output

Following is the output of the above program

 Result= 110 

Go Pointers in Detail

Pointers have many but easy concepts and they are very important to Go programming. The following concepts of pointers should be clear to a Go programmer −

Sr.No Concept & Description
1 Go - Array of pointers

You can define arrays to hold a number of pointers.

2 Go - Pointer to pointer

Go allows you to have pointer on a pointer and so on.

3 Passing pointers to functions in Go

Passing an argument by reference or by address both enable the passed argument to be changed in the calling function by the called function.

Advertisements