Pointers in Go
In Go lang, pointers are special variables that are used to store the memory address of other variables and point to their memory address. Pointers also provide ways to access the value of the variable stored in that address.
The * operator: While declaring a pointer, the pointer name is followed by the type of the variable the pointer points to, prefixed with the * sign as shown below. This is also known as dereferencing the pointer variable.
The following declares a pointer variable of int
type:
var mypointer *int
The above code creates a pointer named mypointer
which points to an int
type variable.
The *
operator is used to make a variable as pointer.
The following example demonstrates the use of pointer.
package main
import "fmt"
func main() {
//Declare a variable
var num int = 100
//Declare a pointer variable
var intPtr *int
//Assign the address of the variable to the pointer
intPtr = &num
fmt.Println(&num) //prints the address of num variable
fmt.Println(intPtr) //prints the address of num variable
fmt.Println(*intPtr) //prints the value of num variable
}
In the above example, var intPtr *int
declares int type pointer.
The intPtr = &num
assigns the address of num
to the pointer intPtr
.
The memory address of this variable is derived by prefixing the &
sign to the variable name as &num
. Now, the pointer intPtr
points to the address of num
.
The fmt.Println(&num)
displays a hexadecimal memory address of the variable num
which can be different in different machine/OS.
So, &num
and intPtr
both display the same address.
To access the value in the memory address the pointer is pointing to, use the asterisk (*) sign in front of the pointer name as *intPtr
. This prints the value 100.
To summarize the pointer operations:
- Pointer variables have to be declared before they can be used.
- It is then assigned the address of another variable by using the
&
operator. - The value of the data in the address is accessed using the
*
operator.
Nil Pointers
If a pointer variable is not assigned to an address of a variable then it is called nil pointer.
Any uninitialized pointer will have <nil>
value.
package main
import "fmt"
func main() {
var intPtr *int
fmt.Println(intPtr) //output: <nil>
}
Passing Pointers to Functions as Arguments
A pointer can be passed as an argument to a function just like passing any other variable. While creating the function, the argument has to be declared as of type pointer.
In the following example, a function is created to accept a pointer as its argument.
package main
import "fmt"
func myfunction(pvar *int){
*pvar = *pvar + 10
}
func main() {
var x int = 25
fmt.Println("Before function call, x = ", x)
//Assign the memory address of the variable x to pointer intPtr
var intPtr *int = &x
// call the function pf and pass pointer intPtr as its argument.
myfunction(intPtr)
fmt.Println("After function call, x = ", x)
//passing address of variable as pointer parameter
myfunction(&x)
fmt.Println("After passing Address, x = ", x)
}
Before function call, x = 25
After function call, x = 35
After passing Address, x = 45
Pointer to a Pointer
A pointer contains the address of a variable. If another pointer is declared pointing to the first pointer which in turn contains the address of a variable, it is called a pointer to a pointer or a double pointer.
A pointer to a pointer is declared with two asterisks prefixed to the type e.g. var ptrB **int
.
In the above figure, pointer ptrA
contains the address of the variable X
and pointer ptrB
holds the address of the pointer ptrA
. You can get the value of X
using *ptrA
.
To get the the value of X
from the double pointer ptrB
, use **ptrB
.
package main
import "fmt"
func main() {
// declare and initialize variable X
var X int = 100
// declare pointer and initialize to the address of the variable X
var ptrA *int = &X
// declare pointer and point to pointer ptrA
var ptrB **int = &ptrA
fmt.Printf("Value of variable X: %d\n", X)
fmt.Printf("Address of variable X: %d\n", &X)
fmt.Printf("Value of pointer ptrA: %d\n", ptrA)
fmt.Printf("Address of pointer ptrA: %d\n", &ptrA)
fmt.Printf("Value of pointer ptrB: %d\n", ptrB)
// dereferencing of pointers. Getting the value of X
fmt.Printf("Value of X from ptrA : %d\n", *ptrA)
fmt.Printf("Value of X from ptrB : %d\n", **ptrB)
}
In the above example, a variable X
is declared and assigned a value of 100. A pointer ptrA
is declared and initialized with the address of the variable. Another pointer ptrB
is declared pointing to the pointer ptrA
.
To get the value of the variable from the double-pointer, two asterisks are prefixed to the double pointer name.
Comparing Pointers
In Go programming, two pointers can be compared with each other. The two pointers will be equal if they point to the same memory location and hence have the same value. The == (equal to) and != (not equal to) operators are used for comparison.
package main
import "fmt"
func main() {
// declare and initialize variable X
var X int = 100
// declare pointer and initialize to the address of the variable X
var ptrA *int = &X
// declare pointer and point to pointer ptrA
var ptrB **int = &ptrA
fmt.Println(ptrA == &X) //true
fmt.Println(*ptrA == X) //true
fmt.Println(ptrB == &ptrA) //true
fmt.Println(*ptrB == ptrA) //true
}
Array of Pointers
In Go, we can create array which stores pointers. The following example shows how to create and use an array of pointers.
package main
import "fmt"
func main() {
arr := []int{10, 20, 30}
var i int
var ptrArr [3]*int;
for i = 0; i < 3; i++ {
//assign the address of each element of arr to ptrArr.
ptrArr[i] = &arr[i]
}
for i = 0; i < 3; i++ {
fmt.Printf("*ptrArr[%d] = %d\n", i,*ptrArr[i] )
}
}
*ptrArr[0] = 10
*ptrArr[1] = 20
*ptrArr[2] = 30
In the above example, ptrArr
is an array of int type pointers that can store 3 pointers.
In the first for loop, the address of each value of arr array is assigned to a member of ptrArr
. In the second for loop, the value (*ptrArr
) held by the array pointers is printed as output.