Source files and packages

Every Go file starts with a package declaration. Files in the same directory must declare the same package. A program is a collection of packages; the entry point is package main with func main().

package main

import "fmt"

func main() {
    fmt.Println("hello")
}

Library packages have any other name. Their directory name should match the package name (idiom, not enforced by the compiler).

Imports

import "fmt"                     // single import
import (
    "fmt"
    "strings"
    iox "io"                     // alias
    _ "image/png"                // import only for side effects (init())
    . "math"                     // dot import — discouraged outside tests
)

Unused imports are a compile error. Use goimports (or your editor) to auto-manage them.

Identifiers and exported names

  • Identifiers are letters and digits, must start with a letter or _.
  • Capitalized names are exported (visible from other packages): fmt.Println is exported, fmt.printer is not.
  • Convention: MixedCaps, not snake_case. Acronyms stay uppercase (URL, ID, HTTPServer).

Comments

// Line comment.

/*
Block
comment.
*/

Doc comments are line comments immediately above an exported identifier:

// Greet returns a friendly greeting for name.
func Greet(name string) string { return "hello, " + name }

go doc and pkg.go.dev render those comments.

Declarations

Variables

var x int           // zero value: 0
var y = 3.14        // type inferred: float64
var z int = 7

var (               // grouped
    a    = 1
    b, c = "go", true
)

n := 42             // short declaration, only inside functions

:= requires at least one new variable on the left-hand side, otherwise use =.

Constants

const Pi = 3.14159
const (
    KB = 1 << 10
    MB = 1 << 20
    GB = 1 << 30
)

iota is an auto-incrementing constant generator inside a const () block:

type Weekday int
const (
    Sunday Weekday = iota   // 0
    Monday                  // 1
    Tuesday                 // 2
    Wednesday               // 3
    Thursday                // 4
    Friday                  // 5
    Saturday                // 6
)

Zero values

Every variable in Go has a defined zero value when declared without an initializer. There is no "undefined" or "garbage" memory.

Type Zero value
Numeric (int, float64, ...) 0
bool false
string ""
Pointer, slice, map, chan, func nil
Struct All fields zeroed

This is why var s []int; s = append(s, 1) is valid even though s was never explicitly initialized.

Naming conventions

  • Short names for short scopes: i for a loop index, r for a *Reader, s for a string.
  • Longer descriptive names for package-level identifiers.
  • Receivers are typically 1–2 letters: func (b *Buffer) Write(...).
  • Error variables are named Err...: var ErrNotFound = errors.New(...).
  • Interfaces with one method are named after the method + er: Reader, Writer, Stringer.

Whitespace and semicolons

Go uses semicolons internally but the lexer inserts them, so you almost never type one. Two consequences:

  • Opening braces must be on the same line as the keyword:

```go if x > 0 { // OK ... }

if x > 0 // COMPILE ERROR: ; inserted before { { ... } ```

  • Statements are line-terminated; you can write multiple on one line with ; but it's not idiomatic.

Run the example

go run ./part1-language/examples/03_lexical