Skip to main content
Forst transpiles to Go. You keep the same module graph, deployment, and ecosystem. See Language overview for syntax. This page covers import paths, Go call lowering, and mixed modules.

Transpile to idiomatic Go

Every .ft file compiles to Go source in your module. The output is an ordinary, readable Go source file. Struct fields, error returns, and control flow follow familiar Go patterns. Shape fields lower to unexported Go identifiers by default. For JSON marshaling (sidecar invoke, HTTP handlers), enable -export-struct-fields or compiler.exportStructFields in ftconfig.json to emit exported fields with json tags. Compile a .ft file to Go:
Run the result with the standard toolchain:

Aligned with Go

Much of Forst mirrors Go syntax: package, import, func, if/for/range, defer, go goroutines. A minimal program can be identical in Forst and Go. See Language overview. Forst adds structural typing, constraints, ensure, and nominal errors on top of that base.

Import Go packages

Call into the standard library and third-party modules with qualified names:
The compiler loads Go packages via go/packages and type-checks Forst↔Go calls when imports resolve. Supported mappings today include primitives, slices, pointers, error, and interface{} (including variadic calls). Go functions that return (T, error) map to Result(T, Error) in Forst at call sites. That applies to the result type of the call and to trailing expressions in implicit returns. This differs from using println / print for void side effects inside a function that should not return a value.

Slice subslices

Forst slice values ([]T) support three-index subslice syntax, lowered to Go slice expressions:
  • xs[low:high] — bounded range
  • xs[low:] — from index through end
  • xs[:high] — from start through index
Given a slice, subslicing looks like this:
See examples/in/slices.ft (task example:slices). Subslices are a language feature on Forst slice values. They are distinct from variadic spread at Go call sites (next section).

Variadic spread into Go calls

When a Go function takes a variadic parameter, spread a Forst slice subslice at the call site with expr[low:].... The compiler lowers this to a Go variadic argument list.
See examples/in/go_interop/cli.ft and helpers.go (task example:go-interop).

Fields and methods on Go values

After a Go call or a local binding typed from Go, use field access and methods with dotted paths:
  • cmd.Run() — method on a *exec.Cmd binding
  • cmd.ProcessState.ExitCode() — field then method
Qualified import calls such as exec.Command(...) are checked when the stdlib package loads from your module workspace (go.mod walk-up sets GoWorkspaceDir).

Forst packages in the same module

An import "module/path" can refer to another Forst package in the same Go module—not only hand-written Go. The compiler resolves these as Forst siblings from .ft sources and the module import map (modulecheck). Cross-package calls type-check against the sibling package’s Forst signatures. This matters for Providers cross-package wiring: api can call auth.LogEvent without a committed Go stub. forst test emits ephemeral lib shims under .forst/gen/test/; the LSP uses the same module-level pass so editor diagnostics match compile-time arity. Try the cross-package provider examples:
Cookbook: examples/in/rfc/providers/cross_pkg/ (auth + api). Do not confuse sibling Forst imports with Go package imports: import "fmt" loads Go via go/packages; import "yourmod/auth" loads a Forst package when auth/ contains .ft files declaring package auth.

Mixed packages

Place .ft files alongside .go in the same module:
Use -root to merge all same-package sources under a tree, matching discovery for forst run, forst build, and the dev server:
The typechecker walks up from your .ft file to find go.mod (GoWorkspaceDir). Exported funcs from co-located .go files resolve without an import line (same package). Example: examples/in/go_interop/helpers.go called from custom.ft / cli.ft.

Project layout profiles

Forst supports three common Go module layouts. Pick one and stay consistent within a project. forst run writes a temp sandbox under .forst/run/ with its own go.mod and links the forst runtime module. Go-native projects (root go.mod, not only .forst-gomod/) use Mode B: an auto-managed .forst/go.work workspace instead of a fragile replace in the sandbox. Node-primary projects keep Mode A (replace forst => … in the sandbox go.mod). For mixed .ft + hand-written .go, prefer forst build and the normal Go toolchain — forst run emits transpiled .go only. Examples: examples/in/go_interop/ (Go-native), examples/in/rfc/node-interop/remix-serve/ (Node-primary with .forst-gomod/go.mod).

Runtime validation

Type constraints in Forst emit runtime checks in generated Go. Untrusted input is validated at the boundary before your handler body executes. See Shapes and constraints.

Providers

Forst Providers (use / with) declare shared runtime services at function boundaries and wire implementations at entry points. See Providers (DI). Run the provider examples:

When to keep hand written Go

  • unsafe or low-level syscalls not yet mapped
  • Large existing packages you are migrating incrementally
  • Performance-critical paths already audited in Go
Forst supports gradual adoption. You can migrate route by route without a big bang rewrite.

Caveats

Go import loading is experimental. Unmapped Go types report diagnostics. This is not a full Go loader yet.

unsafe not end to end

Put unsafe usage in hand written .go and call from Forst. Qualified unsafe.* calls and unsafe.Pointer mapping are not wired through the Forst import path yet.

make and new type args

make and new with a type argument are rejected until Forst type syntax works in that position (e.g. Array(Int), not Go []T).

Slice subslices experimental

Three index subslice syntax on Forst []T values is experimental. It is distinct from variadic spread at Go call sites.

JSON field export

Shape fields lower to unexported Go identifiers by default. For JSON marshaling, see Shapes and constraints § Caveats.

CLI reference

run, build, -root, and compile flags.

Editor workflow

LSP hover for Go imports, godoc, and cross-package Forst siblings.

Node overview

Share types, call Forst from Node, or call JavaScript from Forst.

Call JavaScript from Forst

Call legacy .ts/.js from Forst at runtime.