Summary: in this tutorial, you will learn about Go pointers and how to use them effectively.
Introduction to Go pointers
The following declares a variable x
and initialize its value to 10:
var x int = 10
Code language: Go (go)
In the computer memory, Go places the variable x
at a memory address 0xc00000a0f8
and add the number 10
to this memory location.
Note that the memory address of the variable x
on your computer may be different. Additionally, it may be changed when you restart the program.
To get the memory address of the variable x
, you can use the &
operator:
&x
Code language: Go (go)
For example:
package main
import "fmt"
func main() {
var x int = 10
fmt.Println(&x)
}
Code language: Go (go)
Output:
0xc00000a0f8
Code language: Go (go)
In Go, a pointer is a variable that stores the memory address of another variable. To declare a pointer, you use the following syntax:
var pointer *type
Code language: Go (go)
In this syntax:
var
: var keyword to indicate that a variable declaration.pointer
: specifies the pointer variable name.*type
: specifies the type of variable that the pointer will point to. Like a regular variable, a pointer has a type, meaning that it can point to only a variable with the type specified in the declaration.
For example, to declare a pointer that points to an integer variable, you use the following statement:
var px *int
Code language: Go (go)
The px
is an integer pointer. It can point to a variable of type integer only.
When you declare a pointer without initialization, its value is nil. The nil indicates that the pointer does not point to any variable.
package main
import "fmt"
func main() {
var px *int
fmt.Println(px)
}
Code language: Go (go)
Output:
<nil>
Code language: Go (go)
The following shows how to declare a pointer px and point it to x variable:
package main
import "fmt"
func main() {
x := 10
fmt.Println("The memory addres of x is", &x)
var px *int = &x
fmt.Println("The value of pointer px is", px)
}
Code language: Go (go)
Output:
The memory addres of x is 0xc00000a0f8
The value of pointer px is 0xc00000a0f8
Code language: Go (go)
How it works.
First, declare and initialize the variable x to 10:
x := 10
Code language: Go (go)
Second, display the memory address of x:
fmt.Println(&x)
Code language: Go (go)
Third, declare a pointer px and initialize its value to the memory address of x:
var px *int = &x
Code language: Go (go)
Finally, display the value of the pointer px:
fmt.Println(px)
Code language: Go (go)
The value of the pointer is the same as the memory address of variable x.
Dereference pointers
To get the value of the variable that the pointer points to, you use the * operator:
package main
import "fmt"
func main() {
x := 10
var px *int = &x
fmt.Println("The value of x is", *px)
}
Code language: Go (go)
Output:
The value of x is 10
Code language: Go (go)
In this example, we access the value of x via the pointer using the * operator.
Additionally, you can change the value of the variable x via the pointer using the * operator:
package main
import "fmt"
func main() {
x := 10
var px *int = &x
fmt.Println("The value of x is", *px)
*px = 20
fmt.Println("The value of x is", x)
}
Code language: Go (go)
Output:
The value of x is 10
The value of x is 20
Code language: Go (go)
The * operator
When you place the * operator before a type such as int, you declare a pointer:
var px *int
Code language: Go (go)
But when you place the * operator before a pointer, you dereference that pointer. In other words, you access the value of the variable to which the pointer points to:
*px
Code language: Go (go)
Passing by value
The following program attempts to increase the value of the variable x by one:
package main
func addOne(x int) {
x = x + 1
}
func main() {
x := 10
addOne(x)
println(x)
}
Code language: Go (go)
Output:
10
How it works.
First, define a function addOne that adds one to an argument:
func addOne(x int) {
x = x + 1
}
Code language: Go (go)
Second, declare a variable x and initialize its value to 10:
x := 10
Code language: Go (go)
Third, call the addOne function to add 1 to the variable x:
addOne(x)
Finally, display the value of the variable x:
println(x)
Code language: Go (go)
It doesn’t work as expected.
The reason is that when we pass an argument to a function, Go creates a copy of that argument inside the function. In this example, x inside the addOne() is different from the x inside the main function.
When we change the x inside the addOne() function, we change the copy of x, not change the value of the original x argument:
x = x + 1
Code language: Go (go)
When the addOne()
function returns, the value of x
inside the main()
function remains intact.
To solve this issue, you can use a pointer as follows:
package main
func addOne(px *int) {
*px = *px + 1
}
func main() {
x := 10
addOne(&x)
println(x)
}
Code language: Go (go)
Output:
11
How it works.
First, change the x argument to an integer pointer px:
func addOne(px *int) {
*px = *px + 1
}
Inside the addOne()
function, we add one to the value of the variable that px
pointer points to.
Second, pass the memory address of the x variable to the addOne()
function:
addOne(&x)
In other words, we pass a pointer that points to the x variable to the addOne()
function. In this case, the addOne()
function creates a copy of the px
pointer.
However, this pointer still points to the x
variable inside the main function:
When we increase the value of *px
by one inside the addOne()
function, it changes the value of the x
variable:
*px = *px + 1
Therefore, the change is reflected in the main()
function.
Summary
- A pointer is a variable that stores the memory address of another variable.
- Use a pointer to directly access and change the value stored at a particular memory location.
- Go passes arguments to functions by values.