Hands-on mit Go’s slog Package
Min-jun Kim
Dev Intern · Leapcell

Vorwort
Go Version 1.21.0 führte ein neues Paket log/slog
ein, das strukturierte Protokollierungsfunktionen bietet. Im Vergleich zur traditionellen Protokollierung ist die strukturierte Protokollierung beliebter, weil sie eine bessere Lesbarkeit und erhebliche Vorteile bei der Verarbeitung, Analyse und Suche bietet.
Das slog-Paket
Das slog-Paket bietet strukturierte Protokolle, wobei jeder Protokolleintrag eine Nachricht, eine Schweregrad und verschiedene andere Attribute enthält, die alle als Schlüssel-Wert-Paare dargestellt werden.
Die Hauptmerkmale des slog-Pakets sind:
- Strukturierte Protokollierung
- Protokoll-Schweregrade
- Benutzerdefinierte Protokoll-Handler
- Protokollgruppierung
Erste Erfahrungen
package main import ( "context" "log/slog" ) func main() { // Ausgabe einer einfachen Meldung slog.Info("slog msg", "greeting", "hello slog") // Mit Kontext slog.InfoContext(context.Background(), "slog msg with context", "greeting", "hello slog") }
Im obigen Beispiel geben wir direkt ein Protokoll auf Info-Ebene aus, indem wir die Paketfunktion slog.Info
aufrufen. Intern verwendet diese Funktion eine Standard-Logger
-Instanz, um die Protokollierungsoperation durchzuführen. Darüber hinaus können Sie slog.InfoContext
verwenden, um Protokolle mit einem zugehörigen Kontext auszugeben.
Neben Info()
und InfoContext()
gibt es auch Funktionen wie Debug()
, Warn()
und Error()
für die Protokollierung auf verschiedenen Ebenen.
Das Ausführen des obigen Programms erzeugt die folgende Ausgabe:
2025/06/18 21:08:08 INFO slog msg greeting="hello slog"
2025/06/18 21:08:08 INFO slog msg with context greeting="hello slog"
Einen Logger erstellen
Standardmäßig ist das Format nur Klartext, wenn Sie mit den Slog-Paketfunktionen Protokolle ausgeben. Wenn Sie in JSON oder im Format Schlüssel=Wert ausgeben möchten, müssen Sie eine Logger-Instanz mit slog.New()
erstellen. Wenn Sie diese Funktion verwenden, müssen Sie eine Implementierung von slog.Handler
übergeben. Das Slog-Paket bietet zwei Implementierungen: TextHandler
und JsonHandler
.
TextHandler
TextHandler ist ein Protokoll-Handler, der Protokolldatensätze als eine Reihe von Schlüssel-Wert-Paaren in einen io.Writer
schreibt. Jedes Schlüssel-Wert-Paar wird in der Form Schlüssel=Wert dargestellt, getrennt durch Leerzeichen.
package main import ( "context" "log/slog" "os" ) func main() { textLogger := slog.New(slog.NewTextHandler(os.Stdout, nil)) textLogger.InfoContext(context.Background(), "TextHandler", "Name", "Leapcell") }
Im obigen Beispiel erstellen wir einen Protokoll-Handler mit slog.NewTextHandler
. Der erste Parameter, os.Stdout
, gibt an, dass Protokolle auf der Konsole ausgegeben werden. Der Handler wird dann als Parameter an slog.New
übergeben, um eine Logger-Instanz zu erstellen, die zum Ausführen von Protokollierungsoperationen verwendet wird.
Die Ausgabe des Programms sieht wie folgt aus:
time=2025-06-18T21:09:03.912+00:00 level=INFO msg=TextHandler Name=Leapcell
JsonHandler
JsonHandler ist ein Protokoll-Handler, der Protokolldatensätze im JSON-Format in einen io.Writer
schreibt.
package main import ( "context" "log/slog" "os" ) func main() { jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) jsonLogger.InfoContext(context.Background(), "JsonHandler", "name", "Leapcell") }
Im obigen Beispiel verwenden wir slog.NewJsonHandler
, um einen JSON-Protokoll-Handler zu erstellen. Der erste Parameter, os.Stdout
, gibt die Ausgabe auf der Konsole an. Der Handler wird an slog.New
übergeben, um eine Logger-Instanz zu erstellen, die dann für Protokollierungsoperationen verwendet wird.
Die Programmausgabe sieht wie folgt aus:
{ "time": "2025-06-18T21:09:22.614686104+00:00", "level": "INFO", "msg": "JsonHandler", "name": "Leapcell" }
Globale Logger-Instanz
slog hat eine Standard-Logger-Instanz. Wenn Sie den Standard-Logger erhalten möchten, können Sie sich auf den folgenden Code beziehen:
logger := slog.Default()
In früheren Beispielen haben wir immer eine speziell erstellte Logger-Instanz verwendet, um Protokolle auszugeben. Wenn Sie jedoch nicht jedes Mal über eine bestimmte Logger-Instanz protokollieren, sondern global agieren möchten, können Sie die Funktion slog.SetDefault
verwenden, um die Standard-Logger-Instanz festzulegen und zu ersetzen. Dies macht die Protokollierung bequemer und flexibler.
package main import ( "context" "log/slog" "os" ) func main() { jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) slog.SetDefault(jsonLogger) // Ausgabe mit Kontext slog.InfoContext(context.Background(), "JsonHandler", "name", "Leapcell") //{"time":"2025-06-18T21:11:22.41760604+00:00","level":"INFO","msg":"JsonHandler","name":"Leapcell"} }
Gruppierung
Gruppierung bezieht sich auf das Gruppieren verwandter Attribute (Schlüssel-Wert-Paare) in einem Protokolldatensatz. Hier ist ein Beispiel:
package main import ( "context" "log/slog" "os" ) func main() { jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil)).WithGroup("information") jsonLogger.InfoContext(context.Background(), "json-log", slog.String("name", "Leapcell"), slog.Int("phone", 1234567890)) textLogger := slog.New(slog.NewTextHandler(os.Stdout, nil)).WithGroup("information") textLogger.InfoContext(context.Background(), "json-log", slog.String("name", "Leapcell"), slog.Int("phone", 1234567890)) }
Das Ergebnis der Ausführung dieses Programms sieht wie folgt aus:
{"time":"2025-06-18T21:12:23.124255258+00:00","level":"INFO","msg":"json-log","information":{"name":"Leapcell","phone":1234567890}}
time=2025-06-18T21:12:23.127+00:00 level=INFO msg=json-log information.name=Leapcell information.phone=1234567890
Wenn Sie eine Logger-Instanz mit einem JsonHandler
gruppieren, wird der Gruppenname zu einem Schlüssel, und der Wert ist ein JSON-Objekt, das aus allen Schlüssel-Wert-Paaren besteht.
Wenn Sie einen Logger mit einem TextHandler
gruppieren, wird der Gruppenname mit den Schlüsseln aller Schlüssel-Wert-Paare kombiniert und letztendlich als groupName.key=value
angezeigt.
Effiziente Protokollierung mit LogAttrs
Wenn Sie häufig protokollieren müssen, ist die Verwendung der Funktion slog.LogAttrs
zusammen mit dem Typ slog.Attr
im Vergleich zu den vorherigen Beispielen effizienter, da sie den Prozess der Typparsung reduziert.
package main import ( "context" "log/slog" "os" ) func main() { jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) jsonLogger.LogAttrs(context.Background(), slog.LevelInfo, "Effiziente Logausgabe", slog.String("Name", "Leapcell"), slog.Int("Contact", 12345678901)) }
Im obigen Beispiel verwenden wir die Methode LogAttrs
, um einen Protokolleintrag auszugeben. Die Signatur der Methode lautet:
func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr)
Basierend auf der Signatur ist der erste Parameter ein context.Context
, der zweite Parameter ist ein Level
(der im Slog-Paket definierte Protokollschweregrad) und der dritte Parameter ist ein Schlüssel-Wert-Paar vom Typ Attr
.
Wenn Sie andere Methoden wie Info
verwenden, um Protokolle auszugeben, werden die Schlüssel-Wert-Paare intern in den Typ Attr
konvertiert. Durch die Verwendung der Methode LogAttrs
können Sie den Typ Attr
direkt angeben, wodurch der Konvertierungsprozess reduziert wird und die Protokollierung effizienter wird.
With: Allgemeine Attribute festlegen
Wenn jedes Protokoll dasselbe Schlüssel-Wert-Paar enthalten muss, können Sie erwägen, ein gemeinsames Attribut festzulegen.
package main import ( "context" "log/slog" "os" ) func main() { jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) logger := jsonLogger.With("systemID", "s1") logger.LogAttrs(context.Background(), slog.LevelInfo, "json-log", slog.String("k1", "v1")) logger.LogAttrs(context.Background(), slog.LevelInfo, "json-log", slog.String("k2", "v2")) }
Sie können die Methode With
verwenden, um ein oder mehrere feste Attribute hinzuzufügen und eine neue Logger-Instanz zurückzugeben. Alle Protokolle, die von dieser neuen Instanz ausgegeben werden, enthalten die hinzugefügten festen Attribute, wodurch vermieden wird, dass jedem Protokoll dieselben Schlüssel-Wert-Paare hinzugefügt werden müssen.
Die Ausgabe dieses Programms sieht wie folgt aus:
{"time":"2025-06-18T21:19:51.338328238+00:00","level":"INFO","msg":"json-log","systemID":"s1","k1":"v1"} {"time":"2025-06-18T21:19:51.338604943+00:00","level":"INFO","msg":"json-log","systemID":"s1","k2":"v2"}
HandlerOptions: Konfigurationsoptionen für Protokoll-Handler
Vorsichtige Leser haben vielleicht bemerkt, dass in früheren Beispielen, ob bei der Verwendung von NewJSONHandler
oder NewTextHandler
, der zweite Parameter auf nil
gesetzt wurde, was bedeutet, dass die Standardkonfiguration verwendet wird.
Dieser Parameter ist vom Typ *HandlerOptions
. Damit können Sie konfigurieren, ob der Quellcodeort von Protokollanweisungen angezeigt werden soll, die minimale Protokollausgabeebene und wie Schlüssel-Wert-Paar-Attribute umgeschrieben werden.
package main import ( "context" "log/slog" "os" "time" ) func main() { jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ AddSource: true, Level: slog.LevelError, ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { // Zeitformat if a.Key == slog.TimeKey { if t, ok := a.Value.Any().(time.Time); ok { // Zeit formatieren a.Value = slog.StringValue(t.Format(time.DateTime)) } } return a }, })) // Ausgabe einer einfachen Meldung jsonLogger.InfoContext(context.Background(), "json-log", slog.String("name", "Leapcell")) // Ausgabe einer Fehlermeldung jsonLogger.ErrorContext(context.Background(), "json-log", slog.String("name", "Leapcell")) }
In diesem Beispiel erstellen wir eine Logger-Instanz mit einem JsonHandler
. Beim Erstellen des JsonHandler
werden die folgenden Konfigurationen über den Parameter HandlerOptions
angegeben:
- Ausgabe des Quellcodes (Quellinformationen) der Protokollanweisung
- Festlegen der minimalen Protokollebene auf Error
- Umschreiben des Formats des Attributs mit dem Schlüssel
"time"
in"2006-01-02 15:04:05"
Die Ausgabe dieses Programms sieht wie folgt aus:
{ "time": "2025-06-18 21:21:31", "level": "ERROR", "source": { "function": "main.main", "file": "D:/goproject/src/gocode/play/main.go", "line": 24 }, "msg": "json-log", "name": "Leapcell" }
Die Ausgabe entspricht den Erwartungen: Protokolle der Ebene INFO werden nicht ausgegeben, die Quellinformationen sind enthalten, und der Wert des Schlüssels "time"
wurde umgeschrieben.
Anpassen des Werts in Schlüssel-Wert-Paaren
In einem vorherigen Beispiel haben wir die Konfiguration HandlerOptions
verwendet, um den Wert in einem Schlüssel-Wert-Paar zu ändern. Neben dieser Methode unterstützt das Slog-Paket auch eine andere Möglichkeit, den Wert zu ändern.
package main import ( "context" "log/slog" ) type Password string func (Password) LogValue() slog.Value { return slog.StringValue("REDACTED_PASSWORD") } func main() { // Log attributes slog.LogAttrs(context.Background(), slog.LevelInfo, "Sensitive Data", slog.Any("password", Password("1234567890"))) }
Im obigen Beispiel implementieren wir die Schnittstelle slog.LogValuer
(durch Hinzufügen der Methode LogValue() slog.Value
zu einem Typ), wodurch wir den Wert eines Schlüssel-Wert-Paars überschreiben können. Bei der Protokollierung wird der Wert durch den Rückgabewert der Methode LogValue
ersetzt.
Die Ausgabe dieses Programms sieht wie folgt aus:
2025/06/18 21:37:11 INFO Sensitive Data password=REDACTED_PASSWORD
Wie erwartet wurde der Wert von password
geändert.
Zusammenfassung
Dieser Artikel bietet eine detaillierte Einführung in das Slog-Paket in Go, einschließlich der grundlegenden Verwendung, des Erstellens von Logger-Instanzen, der effizienten Protokollierung und des Anpassens von Protokollinformationen.
Nach dem Lesen dieses Artikels sollten Sie ein tieferes Verständnis des Slog-Pakets haben und in der Lage sein, es effektiver zum Verwalten und Aufzeichnen von Protokollen zu verwenden.
Wir sind Leapcell, Ihre erste Wahl für das Hosten von Go-Projekten.
Leapcell ist die Serverless-Plattform der nächsten Generation für Webhosting, asynchrone Aufgaben und Redis:
Multi-Sprachen-Unterstützung
- Entwickeln Sie mit Node.js, Python, Go oder Rust.
Stellen Sie unbegrenzt Projekte kostenlos bereit
- Zahlen Sie nur für die Nutzung — keine Anfragen, keine Gebühren.
Unschlagbare Kosteneffizienz
- Pay-as-you-go ohne Leerlaufgebühren.
- Beispiel: 25 $ unterstützen 6,94 Mio. Anfragen bei einer durchschnittlichen Antwortzeit von 60 ms.
Optimierte Entwicklererfahrung
- Intuitive Benutzeroberfläche für mühelose Einrichtung.
- Vollautomatische CI/CD-Pipelines und GitOps-Integration.
- Echtzeitmetriken und Protokollierung für umsetzbare Erkenntnisse.
Mühelose Skalierbarkeit und hohe Leistung
- Automatische Skalierung zur einfachen Bewältigung hoher Gleichzeitigkeit.
- Null Betriebsaufwand — konzentrieren Sie sich einfach auf das Bauen.
Erfahren Sie mehr in der Dokumentation!
Folgen Sie uns auf X: @LeapcellHQ