Structs & Methods
With ownership and borrowing established, this chapter combines fields into custom types and gives them behavior — territory Go's own go2-1 (Structs, Methods, Pointers) already covered, making this a natural place for direct side-by-side comparison.
Defining a Struct
A named collection of typed fields, accessed with dot notation — the same basic shape as a Go struct definition.
impl Blocks
Rust keeps a struct's data definition and its behavior definition separate — fields live in struct, methods live in a separate impl ("implementation") block. This is actually a genuine similarity to Go, not a contrast: Go also separates data (the struct) from behavior (a function with a receiver), unlike Java or Kotlin, which bundle both inside one class body.
Methods (&self)
A method's first parameter is &self — a borrowed reference to the instance (Chapter 4's & in action), giving read access to its fields without taking ownership. Called with dot syntax: rect.area().
| Concept | Go | Rust |
|---|---|---|
| Where methods are defined | Outside the struct, with a receiver | Inside a separate impl block |
| Receiver syntax | func (r Rectangle) Area() float64 | fn area(&self) -> f64 |
| Calling a method | rect.Area() | rect.area() |
Associated Functions (No self)
A function inside an impl block without self is an associated function — not a method, and it can't be called on an instance with dot syntax. It's called via Struct::function_name() instead. The most common use is a constructor:
This is exactly the same :: syntax that's already appeared constantly since Chapter 1 — String::from("hello") is nothing more than a call to an associated function named from defined in String's own impl block. Go has no real language equivalent: a Go "constructor" is just an ordinary function following a naming convention (NewRectangle(width, height float64) Rectangle) — Rust's :: namespacing is a genuine language feature tied directly to the type itself, not a convention.
String::from(...) call since Chapter 1 has been calling String's own from associated function — the exact pattern this chapter's Rectangle::new(...) example just defined from scratch. Nothing about it was ever special syntax; it's just a constructor-style associated function, precisely like the ones you can now write yourself.
&self (borrow, read-only), &mut self (borrow, mutable), or plain self (by value) — and that last form genuinely moves the instance into the method, per Chapter 3's move semantics. After calling a method that takes self by value, the original variable is no longer usable at all, exactly like passing it into any other function. Coming from a language where "this"/"self" is always just an implicit reference with no ownership implications, this is an easy trap — reach for &self by default, and use plain self only when a method is deliberately meant to consume the instance (e.g. transforming it into something else).
Coding Challenges
Define a struct Circle with a single field radius (f64). Write a method area(&self) that returns the circle's area (use 3.14159 for pi), and call it on an instance.
📄 View solutionAdd an associated function Circle::new(radius: f64) -> Circle to Challenge 1's struct, and use it to construct an instance instead of the struct-literal syntax.
📄 View solutionExplain the difference between a method and an associated function in Rust, and why Struct::new(...) can't be called as instance.new(...) the way area() can be called as instance.area().
📄 View solutionChapter 5 Quick Reference
- struct Name { field: Type, ... } — defines a custom data type
- impl Name { } — a separate block holding methods and associated functions for that struct
- Method: first parameter is
&self/&mut self/self; called withinstance.method() - Associated function: no
selfparameter; called withStruct::function()— the pattern behind everyString::from(...)call so far selfby value moves/consumes the instance — it's unusable afterward, per Chapter 3's move rules- Rust and Go both separate data (struct) from behavior — unlike Java/Kotlin's class-bundled approach
- Rust's
::constructor pattern is a real language feature; Go'sNewX()is only a naming convention - Next chapter: Enums & Pattern Matching — enums that carry data, the
matchexpression, andOption<T>replacing null entirely