What Is Ampersand in Golang? & and * Pointer Operators Explained

Learn what ampersand means in Go, how & gets a variable address, how * works with pointers, and how & and * are used together in simple examples.

Published

Updated

Read time 4 min read

Reviewed byDeepak Prasad

What Is Ampersand in Golang? & and * Pointer Operators Explained

This guide explains what golang ampersand (&) does, how it pairs with * for pointers, and how that shows up in real code (functions, structs, and a few sharp edges). For a longer tutorial on pointers, see Go pointers tutorial.

Go 1.24 on Linux.


Quick answer: what does & mean in Go?

The unary & operator takes the address of its operand. If x is a variable of type T, then &x has type *T (read “pointer to T”) and points at the storage for x. The unary * in an expression dereferences a pointer: *p is the value p points to. In a type, *T means “pointer to T”—the same character with a different role.


Ampersand and pointers in Go

What is a pointer?

A pointer value holds the address of another value. The zero value of a pointer is nil, meaning it does not point at any valid memory.

What does &variable return?

&variable evaluates to a pointer to that variable. The variable must be addressable (see the address operators in the Go spec).

Pointer types such as *int, *string, *User

Writing *int in a declaration introduces a variable that holds a pointer to an int, not an int value itself:

go
package main

import "fmt"

func main() {
	n := 2022
	var p *int
	p = &n
	fmt.Println("n:", n, "via pointer:", *p)
	*p = 19
	fmt.Println("n after assign through p:", n)
}
Output

You should see n: 2022 and via pointer: 2022, then n after assign through p: 19.


& and * together

  • &x — address of x.
  • *T — type “pointer to T”.
  • *p — value at the address stored in p (dereference).

Go does not support C-style pointer arithmetic: you cannot add integers to a pointer to walk memory.


Ampersand in function arguments

Passing &count lets a function change the caller’s variable through a *int parameter:

go
package main

import "fmt"

func main() {
	x, y := 5, 6
	fmt.Println("before", x, y)
	swapValues(x, y)
	fmt.Println("after swapValues", x, y)
	swapPointers(&x, &y)
	fmt.Println("after swapPointers", x, y)
}

func swapValues(a, b int) {
	a, b = b, a
}

func swapPointers(a, b *int) {
	*a, *b = *b, *a
}
Output

You should see after swapValues still 5 6 (arguments are copied), then after swapPointers as 6 5 because the function mutates the original x and y through their addresses.

Pointer parameters are common for large structs (avoid copying), for optional results (error patterns), and whenever the callee must modify caller state.


Ampersand with structs

Taking the address of a struct literal is idiomatic when you want a *User without a separate var:

go
package main

import "fmt"

type User struct {
	Name string
}

func main() {
	u := &User{Name: "Deepak"}
	fmt.Println(u.Name)
}
Output

You should see Deepak. Field access u.Name works on pointers to structs (Go inserts an implicit dereference); (*u).Name is equivalent but rarely needed.


Slices, maps, channels, and pointers

Slices, maps, and channels are already small reference-like headers: copying the header copies a descriptor, not the whole backing array or map. You usually do not pass &slice into APIs unless you intentionally want a pointer to the header (for example to resize a slice in the caller, or for json.Unmarshal into a pointer). Prefer plain []T, map[K]V, or chan T parameters unless a library or design doc asks for a pointer.


Address vs value

You write Meaning
x the value in variable x
&x address of x
p := &x p is a pointer to x
*p value stored where p points
*p = v store v through p into the pointed-to variable

Mistakes to avoid

  • Taking & of something not addressable, for example a constant literal:
go
package main

func main() {
	_ = &42
}

Building that reports an error like cannot take address of 42 (untyped int constant).

  • Dereferencing a nil pointer at runtime (var p *int; fmt.Println(*p) panics). Always ensure a pointer is non-nil before *p, or guard with checks.
  • Confusing *int (a type) with *p (dereference of variable p). Context tells you which meaning applies.
  • Defaulting to pointers for tiny values (int, bool) when a plain value is simpler and clearer.

Go & and * cheat sheet

Expression Meaning
x value stored in variable x
&x address of x
p := &x p holds a pointer to x
*int type: pointer to int
*p value at address in p
*p = 20 write through the pointer
&User{...} pointer to a new struct value

References


Summary

In Go, & takes the address of an addressable variable and yields a pointer. * in a type means pointer-to-that-type; *p in code reads or writes through the pointer. Together they let functions mutate caller state, build struct pointers with &T{...}, and share large values efficiently. Go omits pointer arithmetic; watch for non-addressable operands, nil dereferences, and unnecessary pointers to slice/map/channel headers when a value argument is enough.


Frequently Asked Questions

1. What does & mean in Go?

The unary & operator takes the address of its operand. For a variable x, &x has type *T where T is the type of x, and the result points at the memory where x is stored.

2. What does * mean in Go?

In an expression, *p dereferences pointer p and yields the value it points to. In a type, *T means pointer to T. Those are different uses of the same symbol.

3. What is the difference between & and * in Go?

& produces a pointer from a variable. *p reads or assigns through that pointer. *int is a type meaning pointer to int.

4. Can I use & on any expression?

No. The operand of & must be addressable (for example a variable or field selector). You cannot take the address of a constant like 42.

5. Does Go have pointer arithmetic like C?

No. You cannot increment a pointer to move through memory. Pointers are for referring to a particular value, not for manual memory arithmetic.

6. Where can I read more about pointers in Go?

Read the companion Go pointers tutorial on GoLinuxCloud, plus the Go specification sections on address operators and pointer types.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise …