Syntax and Comments
Go's syntax is small on purpose. This lesson covers the rules every Go file follows: how a file is laid out, statements and automatic semicolons, blocks and braces, identifiers and keywords, and the two kinds of comments — including doc comments, which become your package's documentation.
The shape of a Go file
Every file has the same three parts, in this order: the package clause, the imports, and then declarations of functions, types, variables and constants in any order.
package main // 1. which package this file belongs to import ( // 2. packages this file uses "fmt" "math" ) // 3. declarations, in any order const radius = 2.5 func area(r float64) float64 { return math.Pi * r * r } func main() { fmt.Printf("A circle of radius %.1f has area %.2f\n", radius, area(radius)) }
A circle of radius 2.5 has area 19.63
main calls area, which is declared above it, but the order doesn't matter: a package-level name can be used anywhere in the package. The grouped import ( … ) form is the usual way to import several packages; gofmt sorts them alphabetically.
Statements and semicolons
Go's grammar uses semicolons, but you almost never type them. The compiler adds one automatically at the end of a line that ends with an identifier, a literal, ), ], }, or keywords such as return and break. Two consequences:
- An opening brace must be on the same line as its
func,if,fororswitch(lesson 3 showed the error). - When you split a long expression or argument list over several lines, end each line with an operator or a comma, so no semicolon is inserted.
package main import "fmt" func main() { total := 1 + 2 + 3 fmt.Println( "total:", total, // the trailing comma is required here ) a, b := 1, 2; fmt.Println(a + b) // two statements on one line: legal, but gofmt would split them }
total: 6 3
(That last line is only there to show the rule. gofmt would put each statement on its own line, and so should you.)
Blocks and braces
Curly braces group statements into a block. Braces are always required — even for a one-line if — and the condition of an if or for has no parentheses:
package main import "fmt" func main() { temperature := 31 if temperature > 30 { fmt.Println("It's hot") } for i := 1; i <= 3; i++ { fmt.Println("lap", i) } }
It's hot lap 1 lap 2 lap 3
Identifiers
Names of variables, functions, types and packages start with a letter or underscore, followed by letters, digits or underscores. They are case-sensitive, and the case of the first letter matters:
| Style | Example | Meaning |
|---|---|---|
| Starts with a capital | Println, MaxSize | Exported: usable from other packages |
| Starts with a lowercase letter | area, userCount | Unexported: private to its package |
Go style is mixedCaps: userCount or UserCount, never user_count. Acronyms keep one case throughout, as in userID, ServeHTTP and parseURL. Short names are normal for short-lived variables (i, n, err); longer, more descriptive names suit things used far from where they're declared.
The underscore on its own, _, is the blank identifier. Assigning to it throws a value away, which is how you ignore a result you don't need.
Keywords
Go has just 25 reserved words, and you can't use them as names:
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 |
Names such as int, string, true, nil, len and append are predeclared rather than reserved. You could technically reuse them, but shadowing them only causes confusion — don't.
Comments
package main import "fmt" /* A block comment can span several lines. It's mostly used to switch off chunks of code. */ func main() { // A line comment runs to the end of the line. fmt.Println("comments are ignored") // it can follow code, too }
comments are ignored
Most Go code uses // line comments, even for long explanations.
Doc comments
A comment placed directly above a package-level declaration, with no blank line between, is a doc comment. Tools such as go doc, your editor's hover help and pkg.go.dev show it as documentation. By convention it is a full sentence that starts with the name being described:
// Package main prints a short shipping quote. package main import "fmt" // FreeShippingThreshold is the order total above which shipping is free. const FreeShippingThreshold = 50.0 // ShippingCost returns the delivery charge for an order total. // Orders at or above FreeShippingThreshold ship for free. func ShippingCost(total float64) float64 { if total >= FreeShippingThreshold { return 0 } return 4.99 } func main() { fmt.Println(ShippingCost(32.50), ShippingCost(75)) }
4.99 0
Write a doc comment for everything exported. go vet doesn't insist on it, but readers of your package will be grateful.
Try it yourself
Add a doc comment and a second function, Discount, that returns 10% of a total.
Shipping: 4.99