A .go file is a source file: a package clause, then import
declarations, then top-level declarations (spec: Source file organization). The language
fixes that order. Everything else on this page, such as which files take part in a build,
comes from the go command and the compiler.
Encoding
Source code is Unicode text encoded in UTF-8 (spec: Source code representation). The text is not normalised, so an accented character written as one code point and the same character built from a letter and a combining accent are different.
- Invalid UTF-8 is rejected by the
gccompiler withinvalid UTF-8 encoding. - Byte order mark. A compiler may ignore a UTF-8 byte order mark
(U+FEFF) as the first code point and may reject one anywhere else.
gcdoes both. - NUL. A compiler may reject the NUL character (U+0000) in the source.
gcdoes. - Line endings. Only line feed (U+000A) ends a line. A carriage return
is ordinary white space, so CRLF files compile. Carriage returns inside
raw string literals
are discarded from the value.
gofmtwrites line feeds only.
Layout of a source file
SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } .
TopLevelDecl = Declaration | FunctionDecl | MethodDecl .
Declaration = ConstDecl | TypeDecl | VarDecl .
// Package greet builds greetings.
package greet
import (
"fmt"
"strings"
)
// Prefix starts every greeting.
const Prefix = "Hello"
// Hello returns a greeting for name.
func Hello(name string) string {
return fmt.Sprintf("%s, %s", Prefix, strings.TrimSpace(name))
}
Comments, blank lines and build constraints may come before the package clause. Imports must come after it and before all other declarations. Top-level declarations may appear in any order and may refer to each other regardless of position, because their scope is the package block.
Package clause
PackageClause = "package" PackageName .
PackageName = identifier .
The package name must not be the blank identifier (spec: Package clause). All the files
that share a package name form that package. The specification allows an implementation
to require them to be in one folder, and the go command does.
- A folder holds one package. The single exception is an
external test package named with a
_testsuffix. package mainis a program; its folder must declarefunc main(). See Packages and modules.- The package clause is not a declaration. The name appears in no scope; it sets the default name used by importers.
- By convention the package name is the last element of the folder path, in lower case with no underscores. Neither is required by the language.
Import declarations
ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
ImportSpec = [ "." | PackageName ] ImportPath .
ImportPath = string_lit .
| Form | Example | How Sin is reached | Use |
|---|---|---|---|
| Plain | import "math" | math.Sin | The usual form |
| Named | import m "math" | m.Sin | Avoid a clash of package names |
| Dot | import . "math" | Sin | Puts the exported names in the file block; discouraged outside tests |
| Blank | import _ "image/png" | Not at all | Run the package’s initialisation only |
- The imported name is declared in the file block, so each file needs its own imports.
- It is an error to import a package and not use it. It is also an error for a package to import itself, directly or indirectly: import cycles are not allowed.
- The meaning of the import path is left to the implementation. The
gocommand treats it as a standard library path or a path inside a module. gofmtsorts the imports within each group; groups are separated by a blank line.
File names and what the go command reads
The language does not care what a source file is called. The go command
decides which files make up a package from their names and their build constraints.
| Name or location | Effect |
|---|---|
Ends in .go | Go source file, considered for the package |
Starts with . or _ | Ignored, as a file or as a folder |
A folder named testdata | Ignored by the go tool; the conventional place for test input |
Ends in _test.go | Compiled only by go test (see test files) |
*_GOOS.go | Implicit constraint: built only for that operating system, as in dns_windows.go |
*_GOARCH.go | Built only for that architecture, as in asm_amd64.go |
*_GOOS_GOARCH.go | Built only for that combination, as in sys_linux_arm64.go |
- The
_testsuffix is stripped before these suffix rules apply, sofoo_linux_test.gois a Linux-only test file. - The suffix needs something before it. A file called
linux.gohas had no implicit constraint since Go 1.4. - The constraint from the name is added to any explicit build constraint in the file.
- Other extensions in the same folder are also examined:
.sand.Sassembler,.c,.hand C++ sources (only useful with cgo or SWIG, otherwise C files are an error),.sysoobject files.
Test files
Files ending in _test.go are compiled only by go test. Their
package clause may name either the package under test or a separate external test
package with a _test suffix, which imports the package like any other
client.
| Function name | Signature | Purpose |
|---|---|---|
TestXxx | func TestXxx(t *testing.T) | A test. Xxx must not start with a lower-case letter |
BenchmarkXxx | func BenchmarkXxx(b *testing.B) | A benchmark |
FuzzXxx | func FuzzXxx(f *testing.F) | A fuzz test |
ExampleXxx | func ExampleXxx() | Documentation example; if the last comment starts with Output: the output is compared |
Build constraints
A build constraint, or build tag, decides whether a file takes part in a build. It is a
line comment of the form //go:build followed by an expression, near the top
of the file, preceded only by blank lines and other comments. In a Go file it must come
before the package clause and should be followed by a blank line, so that it is not read
as package documentation. A file may have only one //go:build line.
//go:build (linux && 386) || (darwin && !cgo)
package hello
&&, ||, ! and parentheses, with their Go meanings| Tag | True when |
|---|---|
linux, windows, darwin… | The target operating system, as in GOOS |
amd64, arm64, 386… | The target architecture, as in GOARCH |
amd64.v2, arm.7… | An architecture feature level, as set by GOAMD64, GOARM and similar |
unix | GOOS is a Unix or Unix-like system |
gc, gccgo | The compiler in use |
cgo | cgo is supported and enabled |
go1.1 … go1.27 | The toolchain is at least that major release. There are no tags for beta or minor releases |
| Anything else | Named with the -tags flag. ignore is the conventional tag for a file that should never be built |
- With
GOOS=android, tags and files forlinuxalso match. The same holds forillumosandsolaris, and foriosanddarwin. - The tag
puregois a convention for a version of a package written only in Go, without assembly. - In modules with Go 1.21 or later, a
go1.Nterm sets a minimum: the language version of the file becomes the minimum version the constraint implies, and this can lower it below the module’s version (see Versions). - The older syntax,
// +build, was used up to Go 1.16.gofmtadds the matching//go:buildline when it finds the old form.
The cgo preamble
A file that uses cgo imports the pseudo-package "C". If the import is
immediately preceded by a comment, that comment, the preamble, is used as a C
header when compiling the C parts of the package. It may contain any C code. Go code
reaches the declarations through the package name C; names that start with a
lower-case letter work too. Static variables in the preamble cannot be used from Go; static
functions can.
package main
// #cgo CFLAGS: -DPNG_DEBUG=1
// #cgo amd64 386 CFLAGS: -DX86=1
// #cgo LDFLAGS: -lpng
// #include <png.h>
import "C"
#cgo lines set compiler and linker flags; they can be limited with build constraintsA #cgo pkg-config: line takes package names and obtains the flags from
the pkg-config tool. A Go function can be made callable from C with a
//export Name comment before it.
Directives
A directive is a comment that the toolchain reads. It must be on its own line, with only
spaces and tabs before it, and with no space between // and the directive
name. Apart from line, compiler directives have the form
//go:name. Tools that do not know a directive skip it as a comment.
| Directive | Read by | Meaning |
|---|---|---|
//go:build expr | go command | Build constraint for the whole file |
//go:embed patterns | go command | Embed files into the variable that follows |
//go:generate cmd args | go generate | Runs a command. Must start at the beginning of the line. Never run by go build |
//go:debug key=value | go command | A GODEBUG default for the program, before the package clause in a main package (Go 1.21) |
//go:noinline | Compiler | Calls to the next function are not inlined |
//go:nosplit | Compiler | The next function omits its stack overflow check; only safe in low-level runtime code |
//go:norace | Compiler | The race detector ignores the next function’s memory accesses |
//go:noescape | Compiler | The next body-less function does not let pointer arguments escape |
//go:uintptrescapes | Compiler | The next function’s uintptr arguments may be converted pointers that must stay alive during the call |
//go:linkname local [path.name] | Compiler | Sets the object-file symbol for a declaration; the file must import unsafe |
//go:wasmimport module name | Compiler | Wasm only: the next body-less function is provided by a host module |
//go:wasmexport name | Compiler | Wasm only: the next function is exported to the host |
//line file:line, /*line file:line:col*/ | Compiler | Sets the reported source position, usually in generated code |
Generated files are marked with a line matching the regular expression
^// Code generated .* DO NOT EDIT\.$ before the first text that is not a
comment or blank.
Embedding files with go:embed
A //go:embed directive (Go 1.16) above a package-level variable declaration
fills the variable with file contents at build time. The file must import
"embed", even if only as a blank import. Only blank lines and
// comments may come between the directive and the declaration, which must
declare a single variable.
package server
import "embed"
//go:embed hello.txt
var greeting string
//go:embed image/* template/*
//go:embed html/index.html
var content embed.FS
string or []byte takes one file; an embed.FS takes many- The variable must be of a string type, a slice of a byte type, or
embed.FS. For a string or byte slice there must be exactly one pattern matching one file. - Patterns use
path.Matchsyntax with forward slashes, relative to the package folder. They may not contain.or..elements, or start or end with a slash. Use*for the current folder. A pattern with spaces can be written as a Go string literal. - A pattern naming a folder embeds its whole subtree, except files whose names begin with
.or_. The prefixall:includes those too. - Patterns cannot match files outside the module, symbolic links,
vendor/, or folders containing ago.mod. Each pattern must match at least one file or non-empty folder, or the build fails.
Documentation comments
A comment placed directly before a top-level package, const, func, type or var
declaration is its documentation comment. The go doc command and
pkg.go.dev read these. The language gives them no meaning. By convention a
comment starts with a complete sentence naming what it documents. A package comment goes
directly before the package clause and starts with Package; it should be in
only one file of the package, and if several files have one they are concatenated. A
paragraph starting Deprecated: is a deprecation notice.
gofmt
gofmt prints Go source in one canonical layout. It uses tabs for indentation
and blanks for alignment, and assumes a fixed-width font. Most Go code is formatted by
it. go fmt runs gofmt -l -w on the named
packages.
| Flag | Effect |
|---|---|
-l | List files whose formatting differs |
-w | Overwrite each file with the formatted version |
-d | Print diffs instead of the output |
-s | Simplify: []T{T{}, T{}} becomes []T{{}, {}}, s[a:len(s)] becomes s[a:], and needless blank range variables go |
-r 'a -> b' | Apply a rewrite rule before formatting |
gofmt only rearranges layout, comments and import order. It does not
change what the code means, apart from what -r and -s ask for.
See Semicolons for why the
opening brace must stay on the same line.