Go deliberately avoids exceptions in favor of explicit error returns. Functions that can fail return an error as their last result, and callers are expected to handle it immediately: result, err := doSomething(); if err != nil { ... }. The error type is itself a built-in interface with a single method, Error() string, so any type implementing that method can serve as an error. Custom errors are typically declared as structs and exposed through a pointer-receiver Error method, while convenience helpers such as errors.New("msg") and fmt.Errorf("wrap: %w", err) cover the common cases. Error wrapping with %w preserves the original cause and enables the inspection helpers errors.Is(err, target), which walks the chain looking for a match, and errors.As(err, &target), which finds the first error assignable to a target type. These patterns let libraries expose rich, structured error information while keeping call sites uncluttered.
Panics represent unrecoverable conditions and propagate up the call stack until a deferred function invokes recover(). Idiomatic Go uses panics sparingly—mostly for true programmer errors or impossible states—rather than for ordinary control flow. A recovered panic can be inspected with if r := recover(); r != nil { ... }, and the program can continue if appropriate. The defer keyword is the partner of recover: it schedules a function call to run after the surrounding function returns, with deferred calls executing in last-in-first-out order. Common uses include closing files, unlocking mutexes, flushing writers, and registering panic-safe cleanup. Because deferred functions still run during a panic propagation, they are the natural place to call recover().
Go's fmt package standardizes formatted output with a set of verbs. %v gives the default representation, %+v includes struct field names, %#v produces a Go-syntax literal, and %T prints the type. Numeric verbs cover integers (%d), floats (%f), strings (%s), and pointer addresses (%p). When a type implements fmt.Stringer—that is, a String() string method—fmt.Println and the %v verb automatically use that method, which is the idiomatic way to give custom types a readable representation. The init function func init() runs automatically before main and is useful for setup that must happen regardless of which entry point runs, such as registering drivers or validating package-level configuration. Package-level variables are initialized in dependency order, then init functions in each file execute in lexical filename order (and, within a file, in declaration order) before main finally begins.