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>
diff --git a/slog-handler-guide/README.md b/slog-handler-guide/README.md
index 0dbb340..cadc501 100644
--- a/slog-handler-guide/README.md
+++ b/slog-handler-guide/README.md
@@ -16,6 +16,7 @@
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 @@
# 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
diff --git a/slog-handler-guide/guide.md b/slog-handler-guide/guide.md
index 578236b..229589b 100644
--- a/slog-handler-guide/guide.md
+++ b/slog-handler-guide/guide.md
@@ -485,7 +485,44 @@
# 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