Skip to content
tezvyn:
Menu

Go's `unsafe` Package: Breaking the Rules for Performance

Source: pkg.go.devMediumHow cards are made

Go's unsafe package lets you bypass type safety, treating memory like C with raw pointers for performance gains. It's used for low-level optimizations and C interoperability. The footgun: its behavior isn't guaranteed across Go versions, making code fragile.

Why it exists

Go is a memory-safe language by design, which ensures program stability but can prevent certain low-level optimizations. The unsafe package provides a deliberate escape hatch for the rare cases where a programmer needs to operate below the type system for maximum performance or interoperability with non-Go code.

The mental model

The unsafe package is a deal with the compiler: you tell it to suspend its type-safety rules, and in return, you get the power to manipulate memory directly, like in C. It gives you two main capabilities: a special unsafe.Pointer that can be cast to any pointer type, and unsafe.Add for pointer arithmetic. This lets you inspect and modify memory layout, but you lose all of Go's safety guarantees. You are telling the compiler, "Trust me, I know what I'm doing."

How it works

The core is unsafe.Pointer, a generic pointer that can be converted to and from other pointer types. A common pattern is converting a TypeA to unsafe.Pointer, then to TypeB to reinterpret the underlying bits. Functions like Sizeof(x), Alignof(x), and Offsetof(x) provide critical information about memory layout. Sizeof returns the size of a type in bytes, while Offsetof returns a struct field's byte offset from the start of the struct. These are essential for performing correct pointer arithmetic.

When to use it

Use unsafe sparingly and only when profiling shows a clear bottleneck. Valid use cases include: first, high-performance serialization/deserialization by mapping a byte slice directly to a struct to avoid allocations; second, interoperating with C libraries via cgo, which requires manual memory management; and third, implementing sophisticated, low-level data structures where you need absolute control over memory layout, as seen in parts of the standard library itself.

When not to use it

Do not use unsafe for clever shortcuts or premature optimization. It makes code harder to read, reason about, and maintain. The biggest danger is that its behavior is not covered by the Go 1 compatibility promise; code that works today might break with a future compiler version. Furthermore, the garbage collector does not track unsafe.Pointer references correctly, which can lead to use-after-free bugs and memory corruption.

One canonical example

A common, dangerous optimization is converting a byte slice to a string without a memory copy. The safe string(mySlice) allocates a new backing array. The unsafe version creates a string header that points directly to the slice's memory. This is fast but breaks Go's immutability guarantee for strings; if the original slice is modified, the string's content will change unexpectedly.

Interview question

What is a primary concern when deciding to use Go's `unsafe` package for performance optimization?

  • a.It automatically converts all pointer types to `unsafe.Pointer`, removing type safety globally.
  • b.It disables the Go runtime's garbage collector for the entire application, leading to unmanaged memory.
  • c.The behavior of code relying on `unsafe` is not guaranteed to remain consistent across future Go versions.Correct
  • d.It introduces significant overhead, often making the code slower than safe alternatives.
Why?

The card explicitly states that `unsafe`'s behavior "is not covered by the Go 1 compatibility promise; code that works today might break with a future compiler version." This makes code fragile and difficult to maintain. While the garbage collector does not track `unsafe.Pointer` references correctly, which can lead to memory corruption, it does not disable the GC entirely for the application.

Just read this? Test yourself on what you have been reading.

Read the original → pkg.go.dev

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on go — each one lists the topics its interview covers.

See open roles