Question

Go Indentation: Tabs, Spaces, and gofmt Formatting

goformattingcoding-styleindentationgofmt

Question

Is there a standard Google Go coding-conventions document that specifies whether Go source code should use tabs or spaces for indentation? What is the official Go recommendation, if one exists?

Short Answer

Go code should normally be formatted with gofmt (or go fmt). The formatter is the practical, official convention: it uses tabs for indentation and spaces for alignment. Rather than manually enforcing a personal indentation style, run the standard formatter consistently.

Concept

Go deliberately avoids making teams debate formatting details. Its standard formatter, gofmt, produces a canonical layout for Go source files.

For whitespace, the important rule is:

  • Tabs indent nested code blocks.
  • Spaces align text in places such as columns or comments.

For example, a statement inside an if block is indented with a tab. If several variable declarations are lined up visually, gofmt may use spaces after the identifiers to align the types or values.

The official Go guidance is generally not a separate Google style guide. Google has internal conventions, but the broadly applicable Go convention is to use the standard Go tools. Code reviewed, shared, and published in the Go ecosystem is expected to be gofmt-formatted.

Mental Model

Think of gofmt as a standard document printer.

You write the content of a Go program; the printer decides the exact spacing, indentation, and line layout. If every developer uses the same printer, every printed copy looks alike. You do not need to negotiate whether one tab equals two, four, or eight spaces—the formatter handles the source representation consistently.

Take Quiz

Syntax and Examples

Format a single Go file:

gofmt -w main.go

Format all packages in the current module:

go fmt ./...

Here is Go code before formatting:

package main

import "fmt"

func main() {
if true {
fmt.Println("formatted by gofmt")
}
}

After gofmt:

package main

import "fmt"

func main() {
	if true {
		fmt.Println("formatted by gofmt")
	}
}

The visible indentation is represented by tab characters. How wide a tab appears is an editor-display setting, but that does not change the Go formatting convention.

gofmt also uses spaces when alignment is helpful:

var (
	name  string
	count int
)

The leading indentation inside the parenthesized declaration is a tab. The spacing between name and string is used for alignment.

Step by Step Execution

Consider this program:

package main

import "fmt"

func classify(score int) string {
	if score >= 60 {
		return "pass"
	}
	return "fail"
}

func main() {
	fmt.Println(classify(75))
}

Step by step:

  1. func classify starts a function block. Its body begins inside { and }, so statements in it are indented one level.
  2. The if statement is inside classify, so it has one leading tab.
  3. return "pass" is inside both the function and the if block, so it has two leading tabs.
  4. The final return "fail" is no longer inside the if, so it returns to one level of indentation.
  5. In main, the call to fmt.Println is inside the function and has one leading tab.

When run, the program prints:

pass

Real World Use Cases

Consistent Go formatting is useful in nearly every kind of Go project:

  • Team repositories: Contributors produce predictable diffs instead of changing whitespace throughout a file.
  • Pull requests: Reviewers can focus on logic, correctness, and tests rather than indentation preferences.
  • Continuous integration (CI): A pipeline can reject code that has not been formatted.
  • Generated or edited API services: Handlers, middleware, and request validation remain easy to scan when all files use the same layout.
  • Open-source packages: Users and contributors expect Go code to follow gofmt output.
  • Editor integration: Most Go-aware editors format a file automatically when it is saved.
Take Quiz

Real Codebase Usage

In real Go codebases, developers treat formatting as automated rather than manual.

Format before committing

A common command is:

gofmt -w .

For a project with generated files or directories that should be excluded, teams usually run gofmt only on selected .go files through a script, formatter integration, or a version-control hook.

Check formatting in CI

A CI job can verify that formatting would not change tracked Go files:

test -z "$(gofmt -l .)"

gofmt -l prints the names of files that need formatting. If it prints nothing, formatting is already correct.

Let the editor do it

A Go editor or language server can run formatting on save. This prevents formatting-only changes from accumulating in a later commit.

Keep style rules separate from formatting

gofmt handles layout, but it does not decide every design question. Teams may additionally use code review guidance and linters for naming, error handling, package design, and suspicious code. Formatting should still be left to gofmt.

Common Mistakes

Manually replacing every tab with spaces

This creates a file that may still compile, but it disagrees with normal gofmt output.

func main() {
    // Four spaces: valid Go, but not gofmt's indentation.
    println("hello")
}

Avoid this by running gofmt -w main.go or enabling format-on-save.

Assuming tab display width changes the source convention

An editor may show a tab as 2, 4, or 8 columns. That affects only how the text looks in that editor. A tab character remains a tab character.

Avoid this by using a comfortable editor display width while allowing gofmt to write the actual file format.

Trying to line up everything manually

Manual columns are fragile when names change.

var short          = 1
var veryLongName   = 2

Write clear code, then let gofmt decide ordinary alignment. It may preserve or adjust spacing according to its rules.

Treating go vet as a formatter

go vet analyzes code for likely mistakes; it does not format source files.

go vet ./...  # Analysis
go fmt ./...  # Formatting

Skipping formatting because the code compiles

The Go compiler accepts many whitespace layouts. Compilation is not proof that code follows the shared style. Run gofmt even when the program builds successfully.

Comparisons

Tool or approachMain purposeChanges indentation and spacing?
gofmtCanonical Go source formattingYes
go fmtRuns the standard formatter through the Go toolchainYes
goimportsFormats Go code and manages importsYes
go vetFinds likely correctness problemsNo
Manual tabs/spacesPersonal editing choicePossible, but should be followed by gofmt
Whitespace typeTypical use in gofmt output
TabIndenting a nested level of code
SpaceAligning items or separating tokens where needed

goimports is often used in editors because it includes formatting while also adding missing imports and removing unused ones. For the basic indentation convention, however, gofmt is the core tool.

Take Quiz

Cheat Sheet

# Rewrite one file using canonical Go formatting
gofmt -w file.go

# Print formatted output without changing the file
gofmt file.go

# Format packages recursively
go fmt ./...

# List files that need formatting
gofmt -l .
  • Use gofmt as the formatting authority for Go source.
  • gofmt uses tabs for indentation.
  • gofmt uses spaces for alignment when appropriate.
  • Tab width is an editor-display preference, not a reason to replace tabs with spaces.
  • Run formatting automatically on save or before committing.
  • Use go vet for analysis, not formatting.

FAQ

Does Go officially use tabs or spaces for indentation?

The standard Go formatter, gofmt, uses tabs for indentation. That formatter defines the convention used by Go projects.

Does Go allow spaces for indentation?

Yes. Go generally compiles regardless of whether indentation uses spaces or tabs. However, running gofmt converts ordinary block indentation to tabs, which is the expected shared style.

Why does Go use tabs for indentation?

Tabs separate the logical indentation level from its visual width. Each developer can choose how wide tabs appear in their editor while source files keep the same indentation characters.

Should I follow a Google Go style guide instead of gofmt?

For Go code shared broadly, follow gofmt. Google-specific internal guidance is not the general authority for Go source formatting; standard Go tooling is.

What is the difference between gofmt and go fmt?

gofmt is the formatting program. go fmt is a Go command that formats packages by running the standard formatter through the Go toolchain.

Does gofmt only fix indentation?

No. It also standardizes spacing, line breaks, declaration layout, and several other presentation details.

Can I configure gofmt to indent with four spaces?

No. gofmt intentionally has a fixed style. Configure your editor's tab display width if needed, but keep the source formatted by gofmt.

Take Quiz

Mini Project

Description

Create a small command-line program that reports a student's result from a score. The program is intentionally simple so you can focus on writing normally structured Go code and using gofmt to apply canonical indentation automatically.

Goal

Write and format a Go program that prints pass for scores of 60 or higher and fail otherwise.

Requirements

  1. Create a main package with a main function.
  2. Add a function named result that accepts an int score and returns a string.
  3. Return pass when the score is at least 60; otherwise return fail.
  4. Print the result for a sample score from main.
  5. Format the file with gofmt -w main.go.
Take Quiz

Keep learning

Related questions

View more