Format Go function and method signatures: signatures longer than a configurable
line length are split with each parameter on its own line; multi-line signatures
that fit on one line are collapsed back. Configuration via .gosigfmt.yaml,
similar to golangci-lint.
gofmt does not split overlong signatures across multiple lines. Long parameter
lists either stay on one wide line or get manually wrapped in inconsistent ways.
gosigfmt enforces a single canonical multi-line layout for signatures over
the limit, and normalizes hybrid forms back to either single-line or
each-param-per-line — nothing in between.
go install github.com/SaintMaximov/gosigfmt/cmd/gosigfmt@latestDownload from Releases. Linux, macOS, and Windows on amd64/arm64.
docker run --rm -v "$PWD:/work" -w /work \
saintmaximov/gosigfmt:latest -l ./...gosigfmt file.go # print formatted source to stdout
gosigfmt -w ./... # rewrite files in place, recursively
gosigfmt -l ./... # CI mode: list files needing formatting (exit 2 if any)
gosigfmt -d ./... # show unified diff
cat file.go | gosigfmt # stdinBefore:
func (s *Server) CreateOrder(ctx context.Context, req *orderpb.CreateOrderRequest, opts ...grpc.CallOption) (*orderpb.CreateOrderResponse, error) {
// ...
}After (line_length: 100):
func (s *Server) CreateOrder(
ctx context.Context,
req *orderpb.CreateOrderRequest,
opts ...grpc.CallOption,
) (*orderpb.CreateOrderResponse, error) {
// ...
}Place a .gosigfmt.yaml at any directory above the files you format. The tool
walks up the directory tree from each file to find the nearest config (similar
to .editorconfig and .golangci.yml). All keys are optional; missing keys
take their default values.
line_length: 100 # max line length
collapse_short: true # collapse multi-line signatures back when they fit
# split_results: how to handle return values when a signature must be split
# auto — split params first; split results only if line still doesn't fit
# always — always split results when params are split
# never — only split params, never touch results
split_results: auto
expand_grouped_params: false # `a, b, c int` stays grouped on split (false)
# or expands to one line per name (true)
targets:
functions: true # top-level funcs and methods
interfaces: true # interface method declarations
generics: true # type parameters: func F[T any](...)
func_literals: false # closures inside expressions
format_test_files: true # include *_test.go
skip_generated: true # skip files marked "Code generated ... DO NOT EDIT."
warn_on_skip: true # print warnings to stderr on skip| Flag | Behavior |
|---|---|
-w |
Write changes back to files in place |
-l |
List files needing formatting (CI mode); exits 2 when any are listed |
-d |
Print unified diff between current and desired format |
--config <path> |
Use this config file; disables discovery |
--no-config |
Ignore .gosigfmt.yaml files; use built-in defaults |
--parallel N |
Worker count (default: GOMAXPROCS) |
--version |
Print version |
-h, --help |
Help |
| Code | Meaning |
|---|---|
| 0 | Success — nothing to format, or formatted successfully |
| 1 | Usage error or unrecoverable read/write/config error |
| 2 | -l mode: at least one file needs formatting |
| 3 | Internal formatter error (please file a bug) |
if [ -n "$(gosigfmt -l ./...)" ]; then
echo "Files need gosigfmt:"
gosigfmt -l ./...
exit 1
fiGitHub Actions step:
- name: gosigfmt
run: |
go install github.com/SaintMaximov/gosigfmt/cmd/gosigfmt@latest
gosigfmt -l ./...gosigfmt is a standard gofmt-style CLI; configure your editor's "format on
save" with the binary path and -w flag. There is no first-party plugin.
- Vim:
autocmd BufWritePost *.go !gosigfmt -w % - VS Code: install Run on Save and configure to invoke
gosigfmt -w ${file}. - GoLand: File Watcher with program
gosigfmt, arguments-w $FilePath$.
| Tool | Splits long signatures | Collapses short multi-line | Configurable line length |
|---|---|---|---|
gofmt |
no | no | no |
goimports |
no | no | no |
golines |
yes (general line wrapping) | no | yes |
gosigfmt |
yes (signatures only) | yes | yes |
gosigfmt is complementary to gofmt and goimports. Run them together; the
output of one is valid input for the other.
- Does not reformat call sites, struct literals, or non-signature constructs.
- Does not touch
functypes in struct fields or variable declarations. - No first-party editor plugin; CLI only.
The project ships a Makefile for common tasks:
make lint # format + run golangci-lint with --fix (via Docker)
make test # go test -race ./...
make build # build the CLI to bin/gosigfmt
make dogfood # build and run gosigfmt -l ./...
make all # lint + test + build + dogfoodmake lint runs golangci-lint inside its official Docker image, so no local install is required (only docker or podman via CONTAINER_ENGINE=podman).
MIT — see LICENSE.