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.
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:
func classifystarts a function block. Its body begins inside{and}, so statements in it are indented one level.- The
ifstatement is insideclassify, so it has one leading tab. return "pass"is inside both the function and theifblock, so it has two leading tabs.- The final
return "fail"is no longer inside theif, so it returns to one level of indentation. - In
main, the call tofmt.Printlnis 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
gofmtoutput. - Editor integration: Most Go-aware editors format a file automatically when it is saved.
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 approach | Main purpose | Changes indentation and spacing? |
|---|---|---|
gofmt | Canonical Go source formatting | Yes |
go fmt | Runs the standard formatter through the Go toolchain | Yes |
goimports | Formats Go code and manages imports | Yes |
go vet | Finds likely correctness problems | No |
| Manual tabs/spaces | Personal editing choice | Possible, but should be followed by gofmt |
| Whitespace type | Typical use in gofmt output |
|---|---|
| Tab | Indenting a nested level of code |
| Space | Aligning 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.
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
gofmtas the formatting authority for Go source. gofmtuses tabs for indentation.gofmtuses 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 vetfor 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.
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
- Create a
mainpackage with amainfunction. - Add a function named
resultthat accepts anintscore and returns astring. - Return
passwhen the score is at least 60; otherwise returnfail. - Print the result for a sample score from
main. - Format the file with
gofmt -w main.go.
Keep learning
Related questions
Are Go Maps Passed by Value or Reference?
Learn Go map parameter and return semantics: maps are passed by value, while copies share underlying data. Know when map pointers are useful.
Authentication for Go REST APIs: Sessions, Tokens, and Middleware
Learn practical authentication patterns for Go REST APIs, including password hashing, server sessions, bearer tokens, middleware, and security rules.
Automatic Build Versioning in Go: Embed Incrementing Build Numbers
Learn how to add automatic build versioning in Go using linker flags, build metadata, CI counters, and Git-based version values.