slog-handler-guide: discuss Record.Clone

Change-Id: I55c6367da953b9a59c4d5cd8ca817d3c051e12de
Reviewed-on: https://go-review.googlesource.com/c/example/+/513138
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
This commit is contained in:
Jonathan Amsterdam 2023-07-26 07:33:34 -04:00
Родитель b766721567
Коммит 6088d5b0e0
2 изменённых файлов: 77 добавлений и 2 удалений

Просмотреть файл

@ -16,6 +16,7 @@ This document is maintained by Jonathan Amsterdam `jba@google.com`.
1. [The `WithGroup` method](#the-`withgroup`-method)
1. [Testing](#testing)
1. [General considerations](#general-considerations)
1. [Copying records](#copying-records)
1. [Concurrency safety](#concurrency-safety)
1. [Robustness](#robustness)
1. [Speed](#speed)
@ -766,7 +767,44 @@ in 65 lines.
# General considerations
TODO(jba): reintroduce the material on Record.Clone that used to be here.
## Copying records
Most handlers won't need to copy the `slog.Record` that is passed
to the `Handle` method.
Those that do must take special care in some cases.
A handler can make a single copy of a `Record` with an ordinary Go
assignment, channel send or function call if it doesn't retain the
original.
But if its actions result in more than one copy, it should call `Record.Clone`
to make the copies so that they don't share state.
This `Handle` method passes the record to a single handler, so it doesn't require `Clone`:
type Handler1 struct {
h slog.Handler
// ...
}
func (h *Handler1) Handle(ctx context.Context, r slog.Record) error {
return h.h.Handle(ctx, r)
}
This `Handle` method might pass the record to more than one handler, so it
should use `Clone`:
type Handler2 struct {
hs []slog.Handler
// ...
}
func (h *Handler2) Handle(ctx context.Context, r slog.Record) error {
for _, hh := range h.hs {
if err := hh.Handle(ctx, r.Clone()); err != nil {
return err
}
}
return nil
}
## Concurrency safety

Просмотреть файл

@ -485,7 +485,44 @@ in 65 lines.
# General considerations
TODO(jba): reintroduce the material on Record.Clone that used to be here.
## Copying records
Most handlers won't need to copy the `slog.Record` that is passed
to the `Handle` method.
Those that do must take special care in some cases.
A handler can make a single copy of a `Record` with an ordinary Go
assignment, channel send or function call if it doesn't retain the
original.
But if its actions result in more than one copy, it should call `Record.Clone`
to make the copies so that they don't share state.
This `Handle` method passes the record to a single handler, so it doesn't require `Clone`:
type Handler1 struct {
h slog.Handler
// ...
}
func (h *Handler1) Handle(ctx context.Context, r slog.Record) error {
return h.h.Handle(ctx, r)
}
This `Handle` method might pass the record to more than one handler, so it
should use `Clone`:
type Handler2 struct {
hs []slog.Handler
// ...
}
func (h *Handler2) Handle(ctx context.Context, r slog.Record) error {
for _, hh := range h.hs {
if err := hh.Handle(ctx, r.Clone()); err != nil {
return err
}
}
return nil
}
## Concurrency safety