02open 25 min

Syntax and structure: from crates and impl blocks to packages, structs, and methods

Map Rust modules, structs, and impl blocks onto Go packages, structs, functions, and methods.

by the end of this lesson you can

  • Uses Go struct syntax
  • Chooses a pointer receiver for mutation
  • Keeps the shape aligned with normal Go code

Overview

Rust developers already understand compiled-code structure, but Go presents it in a flatter way. The important shift is that behavior often lives in plain functions and small methods, with fewer module-level mechanisms than Rust exposes.

In Rust, you often

organize code with crates, modules, structs, enums, and impl blocks that attach associated behavior.

In Go, the common pattern is

to organize code around packages, structs, free functions, and methods where they improve readability rather than mirror every associated function pattern.

why this difference matters

This lesson makes Go feel less underpowered and more intentionally flat.

Rust

struct User {
    name: String,
}

impl User {
    fn greet(&self) -> String {
        format!("hi {}", self.name)
    }
}

Go

type User struct {
    Name string
}

func (u User) Greet() string {
    return "hi " + u.Name
}

Deeper comparison

Rust version

mod config {
    pub struct Settings {
        pub debug: bool,
    }

    pub fn load() -> Result<Settings, ConfigError> {
        Ok(Settings { debug: false })
    }
}

Go version

package config

type Settings struct {
    Debug bool
}

func Load() (Settings, error) {
    return Settings{}, nil
}

Reflect

What gets easier once you stop looking for Rust's module and associated-function structure inside Go code?

what a strong answer notices

A strong answer mentions flatter organization, clearer package boundaries, and less pressure to encode every relationship structurally.

Rewrite

Rewrite this Rust struct-and-impl example into Go using a struct and method.

Rewrite this Rust

struct Counter {
    value: i32,
}

impl Counter {
    fn inc(&mut self) {
        self.value += 1;
    }
}

what good looks like

  • Uses Go struct syntax
  • Chooses a pointer receiver for mutation
  • Keeps the shape aligned with normal Go code

Practice

Design a Go package for request validation starting from a Rust mental model of module plus impl.

success criteria

  • Uses package boundaries intentionally
  • Keeps data and behavior simple
  • Avoids forcing Rust-style organization where Go would be flatter

Common mistakes

  • Looking for impl-style grouping everywhere in Go.
  • Turning ordinary Go functions into methods without a clear readability win.
  • Expecting package organization to mirror Rust modules exactly.

takeaways

  • This lesson makes Go feel less underpowered and more intentionally flat.
  • A strong answer mentions flatter organization, clearer package boundaries, and less pressure to encode every relationship structurally.
  • Uses package boundaries intentionally