8. Pointers
A pointer references a location in memory, and obtaining the value stored at that location is known as de-referencing the pointer. As an analogy, a page number in a book’s index could be considered a pointer to the corresponding page; de-referencing such a pointer would be done by flipping to the page with the given page number.
When there is a value stored in memory, it is stored in a physical location. This location is called its address. Many programming languages, including Go, allows you to access the data in a location by specifying its location in memory.
Unlike C, Go has no pointer arithmetic.
You obtain the address of a variable by using the & symbol before the variable name. Let’s look at a simple example:
Program: ptr1.go
1 package main
2
3 import "fmt"
4
5 func main() {
6 i := 10
7 fmt.Println("The value of i is : ", i)
8 fmt.Println("The address of i is: ", &i)
9 }
The output is:
The value of i is : 10
The address of i is: 0x1043617c
The actual value of the address will differ from machine to machine and even on different executions of the same program as each machine could have a different memory layout and also the location where it is allocated could be different.
Normal programs do not use the numeric value of the address for anything. Instead, what they usually use is the value referenced by the address. You can get the value at an address by using the * symbol before the address.
Let’s look at another example:
Program: ptr2.go
1 package main
2
3 import "fmt"
4
5 func main() {
6 v := 50
7
8 fmt.Println("The value of v is : ", v)
9 fmt.Println("The address of v is : ", &v)
10 fmt.Println("The value at address ", &v, " is: ", *(&v))
11 }
The output is:
The value of v is : 50
The address of v is : 0x1043617c
The value at address 0x1043617c is: 50
When a variable holds an address, it is called a pointer. Therefore in the example ptr := &v, ptr is a pointer and it holds the address the of v. Putting it differently, ptr is a pointer to the variable v. You could also say that ptr is a reference to the variable v.
Let’s look at an example:
Program: ptr3.go
1 package main
2
3 import "fmt"
4
5 func main() {
6 i, j := 20, 5000
7
8 p := &i // point to i
9 fmt.Println(*p) // read i through the pointer
10 *p = 25 // set i through the pointer
11 fmt.Println(i) // see the new value of i
12
13 p = &j // point to j
14 *p = *p / 10 // divide j through the pointer
15 fmt.Println(j) // see the new value of j
16 }
The output is:
20
25
500
Few more examples:
Program: ptr4.go
1 package main
2
3 import "fmt"
4
5 func main() {
6 a := 5
7 var ptr *int
8
9 ptr = &a
10
11 fmt.Println(ptr)
12 }
The output on my machine is:
0x1043617c
new can be applied to types like int, string etc.
Program: ptr5.go
1 package main
2
3 import "fmt"
4
5 func main() {
6 x := new(string) // Here string is a type
7 *x = "Hello"
8 fmt.Println(*x)
9 }
The output is:
Hello
Program: ptr6.go
1 package main
2
3 import "fmt"
4
5 func main() {
6 v := new(int)
7 *v++
8 fmt.Println(*v)
9 }
The output is:
1
|
Exercise 13What’s wrong in the following program: |
1 package main
2
3 func main() {
4 const i = 5
5 ptr1 := &i
6 ptr2 := &10
7 }
8.1 Solutions
Exercise 13 Reason: You can only take the pointer to a variable and not to a literal value or a constant.