Backend Development 17 min read

Understanding and Using Empty Structs (struct{}) in Go

This article explains the zero‑size nature of Go's empty struct, demonstrates how its memory address behaves, shows its impact on struct alignment, and presents multiple practical patterns such as set implementation, large arrays, signal channels, no‑op methods, interface stubs, and the noCopy identifier.

Go Programming World
Go Programming World
Go Programming World
Understanding and Using Empty Structs (struct{}) in Go

In Go, the empty struct struct{} is a special type that contains no fields and occupies zero bytes of memory. Although it seems useless, it has many practical applications.

Zero‑size and address behavior

Using unsafe.Sizeof we can verify that any empty struct instance has size 0. Multiple empty structs may share the same address, but this is not guaranteed; the Go spec states that two distinct zero‑size variables may have the same address . Examples show both identical and different addresses depending on compiler flags and escape analysis.

Effect on memory alignment

When an empty struct is used as a field inside another struct, its position can affect the overall size because of alignment rules. Placing the empty field at the end of a struct may increase the outer struct’s size, while placing it at the beginning does not.

Typical use cases

Set implementation : By combining a map with struct{} values, we can create a memory‑efficient set. type Set map[string]struct{} func (s Set) Add(e string) { s[e] = struct{}{} } func (s Set) Remove(e string) { delete(s, e) } func (s Set) Contains(e string) bool { _, ok := s[e]; return ok } func (s Set) Size() int { return len(s) }

Large capacity arrays : An array of struct{} has size 0 regardless of length, allowing the creation of massive logical arrays without memory cost. var a [1000000]string var b [1000000]struct{} fmt.Printf("array a size: %d\n", unsafe.Sizeof(a)) // 16000000 fmt.Printf("array b size: %d\n", unsafe.Sizeof(b)) // 0

Large capacity slices : Slices always store only a header (pointer, length, capacity). Whether the element type is struct{} or another type, the slice header size remains the same. var a = make([]string, 1000000) var b = make([]struct{}, 1000000) fmt.Printf("slice a size: %d\n", unsafe.Sizeof(a)) // 24 fmt.Printf("slice b size: %d\n", unsafe.Sizeof(b)) // 24

Signal channels : A channel of struct{} can be used as a lightweight notification mechanism because sending a zero‑size value incurs no data copy. done := make(chan struct{}) go func() { time.Sleep(1 * time.Second) fmt.Println("goroutine done") done <- struct{}{} }() fmt.Println("waiting...") <-done fmt.Println("main exit")

No‑op method receivers : Methods that do not need a receiver can use struct{} to avoid allocating memory. type NoOp struct{} func (n NoOp) Perform() { fmt.Println("Performing no operation.") }

Interface stubs : Empty structs implement interfaces without adding overhead, useful for discarding output (e.g., io.Discard ) or creating fake objects in tests. type discard struct{} func (discard) Write(p []byte) (int, error) { return len(p), nil } var Discard io.Writer = discard{}

noCopy identifier : Embedding an empty noCopy struct in a type prevents accidental copying; go vet can detect such misuse. type noCopy struct{} func (*noCopy) Lock() {} func (*noCopy) Unlock() {} type A struct { noCopy; a string }

Conclusion

The empty struct struct{} in Go, despite having no fields and zero size, provides a versatile tool for memory‑efficient data structures, synchronization primitives, placeholder implementations, and compile‑time safety checks. Understanding its behavior helps write clearer, more performant Go code.

Gomemoryinterfacechannelsetempty-structnoCopy
Go Programming World
Written by

Go Programming World

Mobile version of tech blog https://jianghushinian.cn/, covering Golang, Docker, Kubernetes and beyond.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.