Skip to content
tezvyn:
Menu

Structs: Go's Plain Memory vs Rust's Ownership

MediumHow cards are made

Structs bundle named fields into a custom type. Use them when tuples or maps collapse under many values. The footgun is assuming the same syntax means the same rules: Go zero-values fields silently, while Rust demands explicit initialization unless you derive…

Why it exists

Before structs, related data was passed as parallel arrays or loose tuples that decayed into unreadable parameter lists. Structs exist to give a named shape to a bundle of values so the compiler can enforce field access and memory layout. They are the foundational unit of user-defined types in both Go and Rust because neither language relies on classical inheritance for code reuse.

The mental model

Think of a struct as a row in a strictly typed spreadsheet. Each column has a name and a type, and the whole row moves through your program as one value. In Go, that row is a plain contiguous block of memory with compiler-inserted padding to align fields. In Rust, the same row is also a memory block, but it is governed by ownership rules: moving the struct moves all its fields, borrowing it creates references with lifetimes, and you can override memory layout with attributes like repr(C).

How it works

In Go, you declare a struct with the type keyword and attach methods using receiver syntax. The compiler lays out fields in declaration order and inserts padding for alignment; you cannot reorder or pack them without unsafe tricks. A new struct value is automatically zero-valued, meaning every numeric field becomes zero and every pointer becomes nil. In Rust, you declare a struct with the struct keyword and implement behavior in impl blocks. Fields must be fully initialized before the value is considered valid. Rust allows derived traits such as Default, Clone, and Debug to generate boilerplate automatically. Method resolution uses immutable, mutable, or owned self receivers, and the borrow checker verifies that references to struct fields do not outlive the struct itself.

When to use it

Use a struct when a group of values travels together across multiple functions, when you need named fields for clarity, or when you want to define methods on a custom type. They replace maps when you require compile-time field names and replace tuples when the arity exceeds two or three. In Rust, structs are also the gateway to traits; in Go, they are the only way to attach methods to user-defined data.

When not to use it

Do not use a struct as a bag of unrelated globals. If two fields are never accessed together, they belong in separate types. In Go, avoid embedding structs to simulate inheritance; embedding promotes methods and fields but does not create an is-a relationship, and shadowing rules can surprise you. In Rust, do not stuff owned heap data into a struct if you only need temporary views; references inside structs introduce lifetime parameters that infect every call site.

One canonical example

A configuration parser reads host, port, and timeout from environment variables. In Go, you define a Config struct with string and time.Duration fields, then write a Load method that populates it; missing fields are harmless because they default to empty strings or zero durations. In Rust, you define a Config struct with String and u64 fields and derive Default; a builder function or the Default trait fills in sensible values, and the compiler refuses to construct the struct unless every field is accounted for, catching missing initialization at compile time rather than runtime.

Interview question

When creating a struct instance without values for every field, how does Go's behavior differ from Rust's?

  • a.Rust zero-values omitted fields automatically, while Go requires explicit initialization for every field to avoid nil pointers.
  • b.Go silently zero-values omitted fields, while Rust requires explicit initialization for every field unless Default is derived.Correct
  • c.Both languages zero-value omitted fields automatically, but Rust only does so at runtime after the struct is moved.
  • d.Both require explicit initialization for every field, though Go allows pointer fields to remain nil until they are assigned later.
Why?

Go automatically sets omitted fields to their zero values, whereas Rust rejects code with uninitialized fields unless a derived Default provides those values. Distractor A reverses the two languages: Go does not require explicit initialization, and Rust does not zero-value fields automatically.

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

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. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.

See open roles