gofdocs

Modules and Files

The bootstrap module system — local imports, packages, lockfiles, and the current dependency story.

The bootstrap module system is intentionally small and strict.

That is a feature, not a bug. The project is trying to stabilize semantics before pretending that a full package ecosystem already exists.

Local imports

import name now resolves through a deterministic local order:

  1. name.gof next to the importing file
  2. src/name.gof inside the nearest package root with gof.mod
  3. src/lib.gof from a local path dependency declared as name = { path = "../dep" }

Reserved stdlib imports are the one explicit exception:

  • import bytes
  • import io
  • import time
  • import net
  • import http

Those names resolve to shipped modules under stdlib/ instead of local files or dependency aliases. Reusing one of those names in user code is a compile error, not a shadowing trick.

Same-directory imports still work exactly as before.

Package-root imports make it possible to keep entrypoints in subdirectories while sharing one flat package module surface.

Example package:

app/
  gof.mod
  src/
    main.gof
    math.gof

with gof.mod:

module = "example/app"
edition = "2026"

[dependencies]

and src/main.gof:

import math

fn main() -> int:
    return square(9)

Local path dependencies

The current package workflow also supports local path dependencies.

Example app manifest:

module = "example/package_app"
edition = "2026"

[dependencies]
package_math = { path = "../package_math" }

Dependency layout:

package_math/
  gof.mod
  src/
    lib.gof
    ops.gof

src/lib.gof is the dependency entrypoint that gets loaded for import package_math.

Locking the local graph

Manifest-backed packages now use a committed gof.lock.

Generate or refresh it with:

gof mod resolve --dir package_app

Rules:

  • gof.lock is the only lockfile format
  • gof mod resolve is the only command that writes it
  • gof run, gof build, and package-aware gof test require it for manifest-backed packages
  • editing .gof source files alone does not stale the lockfile
  • changing gof.mod metadata or dependency paths does stale the lockfile
  • lockfile entries are deterministic and use forward-slash relative paths

How the current bootstrap graph behaves

Today the module graph:

  • works for same-directory imports
  • works for shipped stdlib imports through reserved module names
  • works for package-root imports through the nearest gof.mod
  • works for local path dependencies through [dependencies]
  • loads imported files into one merged bootstrap module graph
  • rejects import cycles
  • rejects duplicate top-level functions
  • rejects duplicate top-level structs
  • rejects duplicate top-level enums
  • rejects conflicting top-level names across functions, structs, and enums

That strictness exists because constructors, type names, and callable names must stay unambiguous.

How to organize small programs today

The current best practice is:

  • keep a package root with gof.mod
  • keep executable entrypoints in src/main.gof
  • keep reusable package exports in src/lib.gof for dependencies