Go Pointers Explained: A Beginner’s Guide to & and *


September 11, 2025 Program

Go Pointers Explained: A Beginner’s Guide to & and *


Explore how the & and * operators work with simple, practical examples.

In Go, pointers are an essential concept. While you may not use them every day, they become extremely useful when you need to modify external variables, improve performance, or work with large structs. In this article, we’ll explore how the & and * operators work with simple, practical examples.


The Basics

🔗
  • & (address-of operator): gets the memory address of a variable.
  • * (dereference operator): retrieves the value stored at a given memory address.
go
package main

import "fmt"

func main() {
  x := 10
  p := &x  // &x gets the address of x, p is a *int pointer

  fmt.Println("x =", x)   // 10
  fmt.Println("p =", p)   // prints the memory address of x (e.g. 0xc000012090)
  fmt.Println("*p =", *p) // dereference p to get the value of x → 10

  *p = 20 // modify the value through the pointer
  fmt.Println("x =", x)   // 20, because *p changed x
}

Passing by Value vs Passing by Pointer

🔗

By default, Go uses value passing for function arguments, meaning the function receives a copy of the variable. Any changes won’t affect the original. If you want a function to modify the actual variable, you need to pass a pointer.

go
package main

import "fmt"

// Pass by value: does not change the original variable
func addOneByValue(n int) {
  n = n + 1
}

// Pass by pointer: can modify the original variable
func addOneByPointer(n *int) {
  *n = *n + 1
}

func main() {
  a := 5

  addOneByValue(a)
  fmt.Println("after addOneByValue:", a) // 5, unchanged

  addOneByPointer(&a)
  fmt.Println("after addOneByPointer:", a) // 6, modified
}

Pointers with Structs

🔗

When working with structs, passing by value creates a copy of the entire struct. This can be inefficient for large structs, and modifications won’t affect the original. By passing a pointer, you can update the struct directly.

go
package main

import "fmt"

type User struct {
  Name string
  Age  int
}

func updateUser(u *User) {
  u.Age = u.Age + 1
}

func main() {
  user := User{Name: "Alvin", Age: 30}
  updateUser(&user)
  fmt.Println(user) // {Alvin 31}
}

Key Takeaways

🔗
  • &: gets the address of a variable.
  • *: accesses or modifies the value at that address.

Use cases:

  • Modify external variables inside functions.
  • Avoid unnecessary memory copies when working with large structs.
  • Build data structures (linked lists, trees, etc.) that rely on pointers.

Mastering & and * will give you a deeper understanding of Go’s memory model and allow you to write more efficient and powerful code.


Go



Avatar

Alvin

Software engineer, interested in financial knowledge, health concepts, psychology, independent travel, and system design.

Related Posts