Master Go's slog package vocabulary — Handlers, LogAttrs for performance, level filtering, and log grouping.
0 / 5 completed
1 / 5
At standup, a Go developer asks what the slog package is. What is correct?
log/slog was added to the Go standard library in Go 1.21. It provides a Logger type with levelled, structured logging. The key design is a swappable Handler interface — the stdlib ships with JSONHandler and TextHandler. It supersedes both fmt.Println debugging and third-party loggers like zap or logrus for new projects.
2 / 5
In a PR review, a teammate asks about the Handler interface in slog. What is correct?
slog.Handler is a fully exported interface with four methods: Enabled(context.Context, Level) bool, Handle(context.Context, Record) error, WithAttrs([]Attr) Handler, and WithGroup(string) Handler. Implementing this interface lets you build custom backends (sending logs to OpenTelemetry, Datadog, or a structured file format) while the slog.Logger API remains unchanged.
3 / 5
An incident reveals high allocation rates in a hot logging path. A senior engineer recommends LogAttrs. Why?
slog.Info("msg", "key", val) uses the variadic ...any signature, which boxes each value into an interface{} — causing heap allocations. slog.LogAttrs(ctx, level, msg, slog.String(...), slog.Int(...)) accepts pre-constructed slog.Attr values which are structs, avoiding the interface{} boxing and significantly reducing allocations in hot logging paths.
4 / 5
During a design review, the team asks about log levels in the slog package. What is correct?
slog levels are signed integers: LevelDebug = -4, LevelInfo = 0, LevelWarn = 4, LevelError = 8. Any integer value is valid as a level, and you can define custom levels (e.g. LevelTrace = -8, LevelFatal = 12) by creating a type that satisfies slog.Leveler (the Level() slog.Level method). Handlers use Enabled() to filter by minimum level.
5 / 5
In a code review, a developer calls logger.WithGroup("request"). What does this do?
logger.WithGroup("request") returns a new slog.Logger whose Handler nests all subsequent attributes under the "request" key. In JSON output this produces {"request":{"method":"GET","path":"/","latency_ms":12}} rather than flat top-level keys. This prevents key collisions when different subsystems log attributes with the same names (e.g. both HTTP and DB layers having a "duration" field).