Dev Skills

Syntax, comments, and naming

The shape every Go file takes, and the naming rules the whole ecosystem follows.

Topic 2 of 98 · 5 min to read · 45 min to build
After this topic you can
  • Write a Go file with a package clause, an import block, and a doc-commented function.
  • Explain why the opening brace must stay on the same line as func main().
  • Fix the compile errors caused by an unused import and an unused variable.

What syntax means here

Syntax is the set of rules for how Go code must be written down: where the braces go, what counts as a statement, what the compiler will and will not accept. Go keeps its set small on purpose, so there is usually one way to write something.

This topic covers the shape every Go file takes and how to write comments. The next one covers printing. It gets a lesson of its own because it is how you will inspect your program before you ever touch a debugger.

Every file has the same three parts

main.go
package main // 1. which package this file belongs to
import "fmt" // 2. what it needs from elsewhere
func main() { // 3. the code
fmt.Println("hello")
}
The order is fixed: package, then imports, then everything else.

Things that surprise people on day one

  • Semicolons are inserted for you. You almost never type one. This is also why the opening brace must be on the *same* line: func main() followed by { on the next line does not compile.
  • Tabs, not spaces. gofmt decides, and it chooses tabs. Do not fight it.
  • Unused imports and unused variables are compile errors, not warnings.
  • Capitalisation is access control. fmt.Println is exported. A lowercase function inside fmt could not be called from your code.

Comments

comments.go
package main
import "fmt"
// A line comment. This is what you use nearly all the time.
/*
A block comment.
Mostly used to comment out code temporarily.
*/
// Add returns the sum of a and b.
// A doc comment starts with the name of the thing it describes.
func Add(a, b int) int { return a + b }
func main() {
fmt.Println(Add(2, 3)) // a comment can also sit at the end of a line
}
Doc comments starting with the identifier name are read by `go doc` and pkg.go.dev. They are the documentation, not decoration.
calc.go — a package doc comment (excerpt)
// Package calc does arithmetic on money amounts.
package calc
A comment directly above the `package` line documents the whole package. You will write your own packages in **Packages**.

Multiple imports

imports.go
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.ToUpper("one import block, one name per line"))
}
Group imports in brackets once you need more than one. `go fmt` sorts them for you.

Naming rules

  • Letters, digits, and underscore. Must not start with a digit. Case-sensitive.
  • MixedCaps, never under_scores. userID, not user_id.
  • Capital = exported. Name is visible outside the package, name is not.
  • Short names for short lives. i in a loop, n for a count. A package-level name gets a full word.
  • Do not stutter. Callers always write the package name first, so inside package strings the function is ToUpper, not StringsToUpper.
  • Initialisms stay uppercase: URL, ID, HTTP. So userID and parseURL, never userId or parseUrl.

Build this: a name badge

Put the pieces together. Write a program with a doc comment on main, two imports, and a helper function, then run it. Every line here uses something from this lesson.

badge.go
package main
import (
"fmt"
"strings"
)
// badge returns a name framed in a box of stars.
func badge(name string) string {
line := strings.Repeat("*", len(name)+4)
return line + "\n* " + name + " *\n" + line
}
// main prints one badge.
func main() {
fmt.Println(badge("gopher"))
}
Change the name and run it again. Then rename `badge` to `Badge` — it still works, because inside one package capitalisation does not matter.
The short version
  • Package, imports, code: in that order, in every file. Semicolons are automatic.
  • The opening brace must be on the same line, because Go inserts semicolons for you.
  • Unused imports and unused variables are compile errors, not warnings.
  • MixedCaps naming, capital means exported, initialisms stay uppercase (userID, parseURL).
Remember: Capitalisation is not style in Go. It is the access modifier.
Build this before moving on
Write a one-file program with a doc comment on every function, two imports, and a helper that main calls. Then break it three ways (brace on its own line, an unused import, an unused variable) and read each error.
Then try these in your own editor
  1. 1Put the opening brace of func main() on its own line and read the error.
  2. 2Add an unused import and an unused variable, and read both errors.
  3. 3Comment out one line with // and three lines with /* */, and run the program each time.
Check yourselfTake the Getting started test