A DST-based Go source code formatter. Highly opinionated, but very comprehensive. Gofumpt built-in.
Download the latest binary from GitHub Releases.
wormatter <file.go|directory>Formats Go files in place. Recursively processes directories.
task build- Imports — unchanged
- init functions — preserved in original order
- Constants — merged into single
const()block - Variables — merged into single
var()block - Types — grouped by category, each followed by constructors and methods
- Standalone functions — sorted by exportability
- main function — always last
- Blank identifier (
var _ Interface = ...) - Public (uppercase first letter)
- Private (lowercase first letter)
- Sorted alphabetically by first name
- No empty lines between elements
- Single declaration:
const X = 1 - Multiple declarations:
const ( ... )with parentheses
Types are grouped by category (in this order):
- Simple types (aliases like
type MyString string, function types) - Function interfaces (interfaces with exactly one method)
- Non-function interfaces (interfaces with 0 or 2+ methods)
- Structs
Types within each category preserve their original order.
After each type definition:
- Constructors — functions starting with
Newthat return the type - Methods — functions with receiver of that type
A function is a constructor for type T if:
- Name starts with
New - Returns
T,*T,(T, error),(*T, error), etc. - Name after
Newis either exactlyTor starts withTfollowed by non-lowercase charNewFoo✓ matchesFooNewFooWithOptions✓ matchesFooNewFoobar✗ does NOT matchFoo(would matchFoobar)
- Constructors: alphabetically by name
- Methods: exported first, then unexported; within each group sorted by architectural layer
- Exported first, then unexported
- Within each group: sorted by architectural layer (high-level first, utilities last)
Layer is determined by call depth to other local functions:
- Layer 0: functions that call no other local functions (leaves/utilities)
- Layer 1: functions that only call layer 0 functions
- Layer N: functions that call layer N-1 or lower
- Cyclic calls: functions in a cycle share the same layer
Higher layers appear first (orchestrators before utilities).
Fields grouped into three blocks (separated by empty lines):
- Embedded — fields without names, sorted alphabetically by type name
- Public — uppercase names, sorted alphabetically
- Private — lowercase names, sorted alphabetically
When instantiating structs with named fields:
&Config{Timeout: 30, Verbose: true, debug: false}Fields are reordered to match struct definition order (embedded → public → private). No empty lines between fields in literals.
- Empty body stays one line:
func foo() {} - Non-empty body expands to multiple lines
- Empty line before
returnif there's code before it in the same block - No empty line if
returnis the first/only statement
- Single blank line between major sections
- Single blank line between each type definition
- Single blank line between each function/method/constructor
- Double blank lines are compacted to single
- No blank lines within const/var groups (only between groups)