fmt, io, os, bufio, encoding/json, net/http, time, slog, regexp, flag, embed.
time and Duration
The time package has two main types: time.Time (an instant) and
time.Duration (a length of time, expressed as nanoseconds).
Now and intervals
now := time.Now()
fmt.Println(now)
future := now.Add(2 * time.Hour)
elapsed := time.Since(start) // shorthand for time.Now().Sub(start)
fmt.Println(elapsed) // 1.234s
Durations
Constants in the package use natural names:
time.Nanosecond // 1
time.Microsecond // 1000
time.Millisecond // 1_000_000
time.Second // 1_000_000_000
time.Minute
time.Hour
So 2*time.Second + 500*time.Millisecond is "2.5 seconds". A Duration is
just an int64 — you can compare, add, divide, etc.
Formatting is by example
Go's time format string is the reference time:
Mon Jan 2 15:04:05 MST 2006
You rearrange that template to whatever shape you want. So "2006-01-02" is
ISO date, "15:04" is HH:MM, etc.
| Common constant | Example output |
| ----------------- | ----------------------------- |
| time.RFC3339 | 2006-01-02T15:04:05Z07:00 |
| time.Kitchen | 3:04PM |
| time.DateOnly | 2006-01-02 |
| time.TimeOnly | 15:04:05 |
Tickers and timers
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for range ticker.C {
doSomething()
}
ticker.C is a channel — every second a tick arrives. time.After(d) is the
one-shot version (returns a channel that delivers once after d).
Monotonic vs wall clock
time.Now() records both a wall-clock time (good for displaying, sensitive to
NTP / clock changes) and a monotonic reading (always moves forward, good for
measuring durations). Sub and Since use the monotonic part — so they remain
correct even if the system clock jumps.
t.Round and most serialization (JSON, DB) strip the monotonic part. So
time.Since(t) where t came from JSON falls back to wall-clock arithmetic.