[AI生成] 基于slog日志打印
slog是go内置的日志标准库。
支持初始化全局日志设置并打印json日志。
// Package main —— slog global logger demo:
// - JSON format output
// - Beijing time (CST, UTC+8)
// - Source line number (relative path)
// - Request ID (req_id) field
//
// Run: go run ./slog-demo/
package main
import (
"log/slog"
"os"
"path/filepath"
"strings"
"time"
)
// Beijing time location (CST, UTC+8)
var beijingLoc = time.FixedZone("CST", 8*3600)
// Current working directory — used to shorten source.file to a relative path
var wd, _ = os.Getwd()
// init configures the global slog.Logger at package load time
func init() {
opts := &slog.HandlerOptions{
Level: slog.LevelDebug, // Show all levels including Debug
AddSource: true, // Record the source location (file + line)
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
// 1) Convert time to Beijing time
if a.Key == slog.TimeKey {
a.Value = slog.StringValue(a.Value.Time().In(beijingLoc).Format("2006-01-02 15:04:05.000"))
}
// 2) "msg" → "message"
if a.Key == slog.MessageKey {
a.Key = "message"
}
// 3) "level" keeps the default field name (slog default: "level"
// 4) source.file: convert absolute path to relative path
if a.Key == slog.SourceKey {
s := a.Value.Any().(*slog.Source)
file := s.File
if wd != "" {
if rel, err := filepath.Rel(wd, file); err == nil {
file = rel
}
}
// Fallback: keep only the last 2 path components
if strings.Contains(file, string(filepath.Separator)) {
parts := strings.Split(file, string(filepath.Separator))
if len(parts) >= 2 {
file = strings.Join(parts[len(parts)-2:], "/")
}
}
file = filepath.ToSlash(file)
return slog.Attr{
Key: a.Key,
Value: slog.GroupValue(
slog.String("file", file),
slog.Int("line", s.Line),
),
}
}
return a
},
}
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, opts)))
slog.Info("global slog.Logger initialized",
slog.String("timezone", "CST (UTC+8)"),
slog.String("format", "JSON"),
)
}
// ============================================================
// Business scenario: simulate a login request handler
// ============================================================
// handleLogin simulates a login request.
// For each request, create a child logger with req_id — every log in this
// request will automatically carry the req_id field.
func handleLogin(reqID, username, ip string) {
log := slog.With(slog.String("req_id", reqID))
log.Info("start processing login request",
slog.String("username", username),
slog.String("client_ip", ip),
)
log.Debug("querying users table",
slog.String("table", "users"),
slog.String("query", "SELECT * FROM users WHERE username = ?"),
)
log.Info("login succeeded",
slog.String("username", username),
slog.Int("user_id", 10086),
)
}
// ============================================================
// Main
// ============================================================
func main() {
slog.Info("application started")
handleLogin("req-001", "alice", "192.168.1.10")
handleLogin("req-002", "bob", "192.168.1.20")
slog.Info("application exited normally")
}

浙公网安备 33010602011771号