Go by Example: Advanced Logging with Zap
Go 1.23
Achieve high-performance structured logging with Uber's Zap library. This example compares the type-safe, zero-allocation `Logger` with the more convenient `SugaredLogger`, demonstrating how to log structured data efficiently.
Code
package main
import (
"go.uber.org/zap"
"time"
)
func main() {
// Create a production logger
logger, _ := zap.NewProduction()
defer logger.Sync() // flushes buffer, if any
// Structured logging
logger.Info("failed to fetch URL",
zap.String("url", "http://example.com"),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
// Sugared logger for printf-style logging
sugar := logger.Sugar()
sugar.Infow("failed to fetch URL",
"url", "http://example.com",
"attempt", 3,
"backoff", time.Second,
)
sugar.Infof("Failed to fetch URL: %s", "http://example.com")
}Explanation
Uber's zap is a high-performance, zero-allocation structured logging library. While Go 1.21 introduced log/slog, Zap remains a popular choice for extreme performance requirements.
Zap provides two logger types:
zap.Logger: The fastest option. It requires strongly-typed fields (e.g.,zap.String("k", "v")) and avoids reflection entirely.zap.SugaredLogger: A more ergonomic, printf-style logger (e.g.,sugar.Infow("msg", "k", "v")). It is slightly slower but easier to write.
Structured logging is essential for modern observability, allowing logs to be easily queried in tools like Elasticsearch or Datadog.
Code Breakdown
10
zap.NewProduction() creates a logger optimized for production environments. It logs at Info level and above, uses JSON formatting, and writes to stderr.
11
defer logger.Sync() ensures that any buffered log entries are flushed to the underlying writer before the program exits. This is critical to avoid losing logs.
14-18
Structured logging with the base Logger. We pass a message string and then a series of strongly-typed fields (zap.String, zap.Int, zap.Duration). This avoids reflection overhead and ensures type safety.
21
logger.Sugar() converts the base Logger into a SugaredLogger. This allows for a more familiar, printf-style API at the cost of a small performance hit.
22-26
Using the SugaredLogger. Note how we can mix the message with key-value pairs directly ("url", "http...", "attempt", 3) without needing specific field constructors like zap.String.

