Syntax#
Go’s grammar is small, C-shaped, and rigidly formatted. Source
files start with package and import; statements end at
newlines (the lexer inserts implicit semicolons). gofmt is
the only formatter; never argues style.
/types`. For operators, see Operators.
package main
import "fmt"
func greet(name string) {
fmt.Println("hello,", name)
}
func main() {
greet("operator")
}
Identifiers#
Letters, digits, and underscores; cannot start with a digit.
Case controls visibility: identifiers starting with an
uppercase letter are exported from the package; lowercase
identifiers are package-private. Convention is camelCase for
locals and unexported names, PascalCase for exported names,
UPPER_SNAKE only for constants imported from other
ecosystems.
var userCount int // unexported
const MaxRetry = 5 // exported
type HTTPClient struct {} // exported; acronyms stay uppercase
The blank identifier _ discards a value it does
not want to bind.
_, err := os.Stat("file") // we only care about the error
Keywords#
Reserved words.
break case chan const continue default defer else fallthrough
for func go goto if import interface map package range return
select struct switch type var
Predeclared identifiers (true false nil iota, builtin
functions make new len cap append copy delete panic recover,
types int string bool error any…) are not reserved but the
operator does not shadow them.
Literals#
Every primitive has a literal form.
n := 42 // int
big := 1_000_000 // underscore separators (Go 1.13+)
x := 0xff // hex
o := 0o755 // octal (Go 1.13+ form; older 0755 still works)
b := 0b1010_0001 // binary
pi := 3.14159 // float64
e := 6.022e23 // scientific
s := "hello" // string (interpreted)
r := `no \n escapes` // raw string (backticks); spans lines
c := 'A' // rune (int32)
t := true
z := nil // valid only for pointers, interfaces, slices,
// maps, channels, and functions
Statements#
A statement does something. Assignment, import,
return, defer, go, if / for / switch /
select blocks, function calls.
x := 1 + 2 // short variable declaration
import "fmt" // import declaration
if x > 0 {
fmt.Println("positive")
}
for i := 0; i < 3; i++ {
fmt.Println(i)
}
return x
Semicolons separate statements; the lexer inserts them at
newlines following an identifier, literal, ), ], },
or specific keywords. Never writes them
explicitly.
Expressions#
An expression evaluates to a value. Arithmetic, function calls, type conversions, composite literals, and channel receives are all expressions.
1 + 2 // arithmetic
len(xs) > 0 // relational
fmt.Sprintf("%d", n) // function call
[]int{1, 2, 3} // composite literal
<-ch // channel receive
Go has no ternary; write a four-line if or a
helper function.
Blocks#
A block is a { ... } braced group. Every if, for,
switch, select, and func body is a block. The
opening brace must be on the same line as the keyword (the
semicolon-insertion rule would otherwise terminate the
statement).
if x > 0 { // OK
// ...
}
if x > 0
{ // syntax error
// ...
}
Comments#
Line comments start with
//; block comments wrap with/* ... */(do not nest). A comment immediately above a top-level declaration is the doc comment and shows up ingo docandpkg.go.dev.