1. Go Fundamentals
A fast orientation to Go's philosophy, modules, toolchain, visibility, and binaries.
Question: What are the key characteristics of the Go programming language?
Answer: Go is a statically typed, compiled language known for its built-in concurrency features, garbage collection, and simple syntax. It compiles to a single binary that is often self-contained; with CGO_ENABLED=0
, builds are fully static.
Explanation: Go's design philosophy emphasizes simplicity, readability, and efficiency for modern networked services. Concurrency is a first-class citizen, handled through lightweight goroutines and channels. Error handling is managed explicitly through return values rather than exceptions, and its built-in tooling is powerful and easy to use.
Question: How does Go handle visibility for packages (e.g., public vs. private)?
Answer: Go uses a simple convention based on naming: any identifier (like a variable, function, or type) that starts with a capital letter is exported (public). Identifiers starting with a lowercase letter are unexported (private) to the package.
Explanation: This rule, known as "casing for visibility," eliminates the need for explicit keywords like public
or private
. It's a core part of Go's idiomatic style and makes code easy to read.
package mypackage
var ExportedVar int // Accessible from other packages
var privateVar int // Not accessible
Question: What are some of the most common commands in the Go toolchain?
Answer: The most common commands are go run
to compile and execute a program, go build
to compile a binary, go test
to run tests, go fmt
to format code, and go mod tidy
to manage dependencies.
Explanation: The Go toolchain is known for its simplicity and power. Other critical commands include:
go test -race
: To detect data races in concurrent code.go vet
: A static analysis tool that finds suspicious constructs.go mod init
: To initialize a new module.
Question: What are
go.mod
andgo.sum
, and how do you manage modules?
Answer: go.mod
declares your module path and dependency requirements. go.sum
records checksums to verify module contents. Use go mod init
to create a module and go mod tidy
to add missing and remove unused dependencies.
Explanation: Modules make builds reproducible and secure. Keep both files under version control. The Go proxy ecosystem caches modules; checksums in go.sum
ensure integrity. Typical workflow: initialize with go mod init example.com/your/app
, import packages in code, then run go mod tidy
.
Question: Modules vs GOPATH — what changed and how do I structure projects today?
Answer: Modules replaced GOPATH as the default dependency and build system. Put a go.mod
at the repo root; code can live anywhere on disk, not under $GOPATH/src
.
Explanation: Since Go 1.16+, modules are the default. Use semantic import paths (module/path/pkg
). Pin deps in go.mod
, verify via go.sum
. For multi-module repos, prefer one module per deployable unless you have a strong reason to split.
Question: What does
package main
mean, and how domain()
andinit()
work?
Answer: package main
builds an executable. The entrypoint is func main()
. init()
runs before main()
and before each package is used; avoid heavy logic there.
Explanation: Each package can have multiple init()
functions (file order is unspecified). Init runs after variable initialization and import dependency order. Prefer explicit setup in main()
with clear errors rather than hidden work in init()
.
Question: What is a "zero value" in Go?
Answer: In Go, every variable declared is automatically initialized to its "zero value" if no explicit value is provided. For numeric types, it's 0
; for strings, ""
; for booleans, false
; and for pointers, functions, interfaces, slices, channels, and maps, it's nil
.
Explanation: This design choice ensures that variables are always in a predictable state, preventing "uninitialized variable" errors common in other languages. Many Go types, like sync.Mutex
or bytes.Buffer
, are designed to be useful in their zero-value state.
Question: How do you format and lint Go code idiomatically?
Answer: Use gofmt
/go fmt
(and goimports
) to format automatically; use go vet
for static checks; optionally add staticcheck
for deeper diagnostics.
Explanation: Formatting is non-negotiable in Go—gofmt
enforces a single style. goimports
also fixes imports. go vet
catches suspicious constructs; staticcheck
provides additional best-practice checks.
Question: What role does
GOPATH
play today with modules?
Answer: You no longer need to keep source under GOPATH
. It now primarily hosts the module and build caches (e.g., GOPATH/pkg/mod
).
Explanation: With modules, projects can live anywhere on disk. Inspect with go env GOPATH
.
Question: What is the difference between a package name and an import path?
Answer: The import path is how other code references your package (e.g., github.com/me/app/pkg/db
); the package name is the identifier you write after package
and use in code.
Explanation: Package names are usually the last segment of the import path, but need not match directories exactly. Prefer short, meaningful names like db
, httpx
.