Własne handlery
Buduj własny format danych wyjściowych logów
Własne handlery to bezpłatna lekcja Go Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Go Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Go Academy zawiera 4 lekcji w sumie.
Kiedy wbudowane handlery nie wystarczają
Handlery tekstowe i JSON pokrywają większość potrzeb, ale czasami potrzebny jest niestandardowy format danych wyjściowych: kolorowy terminal, wysyłanie danych do systemu metryk albo usuwanie sekretów. W takiej sytuacji należy zbudować niestandardowy handler.
Interfejs Handler
Handler implementuje cztery metody:
Enabled(ctx, level) boolHandle(ctx, record) errorWithAttrs(attrs) HandlerWithGroup(name) Handler
type Handler interface {
Enabled(context.Context, slog.Level) bool
Handle(context.Context, slog.Record) error
WithAttrs(attrs []slog.Attr) slog.Handler
WithGroup(name string) slog.Handler
}Enabled steruje filtrowaniem
Enabled jest wywoływana przed utworzeniem rekordu. Zwrócenie wartości false pozwala slog całkowicie pominąć tę pracę, dlatego należy używać tej metody do sprawdzania poziomu.
func (h *MyHandler) Enabled(_ context.Context, l slog.Level) bool {
return l >= slog.LevelInfo
}Handle wykonuje pracę
Handle otrzymuje obiekt slog.Record zawierający czas, poziom, komunikat i atrybuty. Można sformatować i zapisać te dane w dowolny sposób.
func (h *MyHandler) Handle(_ context.Context, r slog.Record) error {
fmt.Printf("[%s] %s\n", r.Level, r.Message)
return nil
}Iterowanie po atrybutach
Obiekt Record udostępnia swoje atrybuty za pośrednictwem r.Attrs, które wywołuje przekazaną funkcję dla każdego z nich.
r.Attrs(func(a slog.Attr) bool {
fmt.Printf(" %s=%v\n", a.Key, a.Value)
return true // keep going
})WithAttrs i WithGroup
Metody te zwracają kopię handlera zawierającą wstępnie ustawione atrybuty lub prefiks grupy. Obsługują one logger.With i slog.Group. Minimalny handler może przechowywać te dane i odtwarzać je później albo, na potrzeby nauki, zwracać siebie.
Opakowywanie zamiast budowania
Często nie trzeba tworzyć całego handlera. Można opakować istniejący handler i zmienić tylko wybrane zachowanie, na przykład dodać stały atrybut albo usuwać klucze.
type RedactHandler struct{ slog.Handler }
func (h RedactHandler) Handle(ctx context.Context, r slog.Record) error {
// mutate r here, then delegate
return h.Handler.Handle(ctx, r)
}Przypadek użycia: usuwanie poufnych danych
Handler usuwający poufne dane może wyszukiwać wśród atrybutów wrażliwe klucze, takie jak password lub token, i zastępować ich wartości przed przekazaniem danych do handlera JSON.
Przypadek użycia: routowanie
Niestandardowy handler może routować logi według poziomu: wysyłać logi Error do stderr i webhooka systemu alertów, a logi Info do stdout. Dzięki temu logika routowania nie musi znajdować się w każdym miejscu wywołania.
Uwagi dotyczące wydajności
Metoda Handle może być wykonywana w często używanych ścieżkach. Należy unikać alokacji, sprawdzać poziom w Enabled i ponownie wykorzystywać bufory. Z tego powodu standardowe handlery wewnętrznie korzystają z bufora z puli.
Program uruchamialny: minimalny niestandardowy handler
Ten samodzielny program definiuje niewielki handler, który wypisuje poziom, komunikat i atrybuty, a następnie zapisuje za jego pomocą log.
package main
import (
"context"
"fmt"
"log/slog"
)
type Mini struct{}
func (Mini) Enabled(context.Context, slog.Level) bool { return true }
func (Mini) WithAttrs(a []slog.Attr) slog.Handler { return Mini{} }
func (Mini) WithGroup(string) slog.Handler { return Mini{} }
func (Mini) Handle(_ context.Context, r slog.Record) error {
fmt.Printf("%s: %s", r.Level, r.Message)
r.Attrs(func(a slog.Attr) bool {
fmt.Printf(" %s=%v", a.Key, a.Value)
return true
})
fmt.Println()
return nil
}
func main() {
l := slog.New(Mini{})
l.Info("hello", "user", "ada", "id", 7)
}Szybkie sprawdzenie
Sprawdź, czy rozumiesz niestandardowe handlery.
Podsumowanie
Nauczyli się Państwo budować niestandardowe handlery:
- Należy zaimplementować
Enabled,Handle,WithAttrsiWithGroup - Ze względów wydajności sprawdzanie poziomu należy wykonywać w
Enabled - Atrybuty należy przeglądać za pomocą
r.Attrs - Często łatwiej jest opakować istniejący handler, niż budować go od podstaw
Często zadawane pytania
Czy lekcja „Własne handlery” jest bezpłatna?
Tak — pełny tekst „Własne handlery” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Go Academy, przejdź na CoddyKit PRO. Kurs Go Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Własne handlery”?
Buduj własny format danych wyjściowych logów Ćwiczysz Go Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Go Academy?
Nie wymagamy żadnego doświadczenia. Go Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Własne handlery”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Go Academy?
Tak. Każda lekcja Go Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.