Skip to main content

Pointers

In Go, pointers are variable that hold the memory addresses of other variables. Using pointers , you can access and modify the values stored in the memory directly, allowing you to work efficiently with memory and optimize performance.

1. Declaring and Using Pointers

You declare a pointer using the * symbol, which specifies the type it points to. The & operator is used to get the memory address of a variable.

package main

import "fmt"

func main() {
x := 10
p := &x // p now holds the address of x
fmt.Println(p) // Output: (memory address of x, e.g., 0xc000014080)
fmt.Println(*p) // Output: 10 (value of x)
}
  • Here, p is a pointer to x, and *p dereferences p, giving the value stored at the address p.

2. Modifying Values Through Pointers

Pointers allow you to modify the value of a variable indirectly by accessing it through its address.

package main

import "fmt"

func main() {
x := 10
p := &x
*p = 20 // Changes the value at the address of x
fmt.Println(x) // Output: 20
}

3. Using Pointers in Functions

When passing a variable to a function, Go passes a copy of that variable by default. By using pointers, you can pass the memory address instead, allowing the function to modify the original variable.

package main

import "fmt"

func increment(n *int) {
*n = *n + 1
}

func main() {
x := 10
increment(&x) // Passing the address of x
fmt.Println(x) // Output: 11
}
  • The increment function receives a pointer and increments the value at that address. This change is reflected in x.

4. Nil Pointers

A pointer that doesn't point to any memory address is called a nil pointer, which is Go’s way of saying the pointer is uninitialized or empty.

package main

import "fmt"

func main() {
var p *int // p is a nil pointer
fmt.Println(p) // Output: <nil>
if p == nil {
fmt.Println("p is nil")
}
}
  • Declaring a pointer without initializing it results in a nil pointer.

5. Pointers to Structs

You can create pointers to structs, which is useful when passing large structs to functions. Accessing fields through a pointer does not require explicit dereferencing.

package main

import "fmt"

type Person struct {
Name string
Age int
}

func main() {
p := &Person{"Alice", 30}
fmt.Println(p.Name) // Output: Alice
fmt.Println(p.Age) // Output: 30
}
  • Here, p is a pointer to a Person struct. We can access Name and Age directly as Go automatically dereferences struct pointers.

6. Pointers and Arrays

Pointers can also point to arrays, allowing you to access and modify array elements through pointers.

package main

import "fmt"

func main() {
arr := [3]int{10, 20, 30}
p := &arr
(*p)[0] = 15 // Modifying first element through pointer
fmt.Println(arr) // Output: [15 20 30]
}
  • p is a pointer to arr, and we modify arr[0] through *p.

7. Slice Pointers

Slices are already reference types in Go, so passing a slice to a function doesn’t require a pointer to modify the original slice. However, you can still create pointers to slices when needed.

package main

import "fmt"

func updateSlice(s *[]int) {
(*s)[0] = 100
}

func main() {
slice := []int{1, 2, 3}
updateSlice(&slice)
fmt.Println(slice) // Output: [100 2 3]
}

8. Pointers with Maps and Channels

Maps and channels are also reference types, so pointers aren’t necessary for modifying the original values when passed to functions. However, you can use pointers to maps and channels if needed.

package main

import "fmt"

func updateMap(m *map[string]int) {
(*m)["key"] = 100
}

func main() {
m := map[string]int{"key": 1}
updateMap(&m)
fmt.Println(m) // Output: map[key:100]
}

Summary of Common Pointer Operations

OperationExampleDescription
Declare a Pointervar p *intDeclares a nil pointer of type *int.
Assign Address to Pointerp := &xAssigns the address of variable x to pointer p.
Dereference a Pointer*pAccesses or retrieves the value stored at the address p points to.
Modify Value via Pointer*p = 20Changes the value at the address p points to.
Check for nil Pointerif p == nil { ... }Checks if a pointer is nil (uninitialized or empty).
Pass Pointer to Functionincrement(&x)Passes the address of x to a function, allowing modification of x directly.
Pointer to Structp := &Person{"Alice", 30}Creates a pointer p to a struct. Fields can be accessed with p.FieldName.
Pointer to Arrayp := &arrCreates a pointer to an array, allowing access to or modification of array elements via *p.
Pointer to Slicep := &sliceCreates a pointer to a slice. Slices are reference types, so pointer use is rare but possible.
Pointer to Mapp := &mCreates a pointer to a map. Maps are reference types, so pointer use is uncommon but allowed.
Pointer to Channelp := &chCreates a pointer to a channel. Channels are reference types, so pointers are rarely needed.