The Attr type

July 2, 2026

Other than logger methods, the slog.Attr type is probably the thing you’ll use the most in your use of the slog package:

Types

type Attr

type Attr struct {
	Key   string
	Value Value
}

An Attr is a key-value pair.

This type has several type-specific constructors, too, but we’re going to do an abbrevaited look at them, because they’re highly repetitive.

func Any

func Any(key string, value any) Attr

Any returns an Attr for the supplied value. See AnyValue for how values are treated.

Any provides the general-purpose way to create an Attr for any type.

var foo struct  {
  Some   int
  Random string
  Fields float64
}

slog.Any("foo", foo{})
slog.Any("bool", true) // Functionally equivalent to using slog.Bool

Notably, slog.Any can be used for types that also have their own constructors, listed below. The only difference in using the type-specific constructors is that they don’t have to do any runtime type assertion.

func Bool

func Duration

func Float64


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Expanding errors with ReplaceAttr

Let’s look at one other example where I reach for ReplaceAttr regularly: Logging additional error detail. (I talk more about this approach in my Boot.Dev course Learn Logging and Observability in Go (see below for a discount code).) For this technique to be meaningful, I first need errors that contain additional details. And this can take many forms, but probably the most ubiquitous form is an error that contains a stack trace, such as those produced by the popular package github.


Test logging with ReplaceAttr

Today’s topic is probably the most interesting, subtle, and complicated of the three HandlerOptions fields: ReplaceAttr. type HandlerOptions type HandlerOptions struct { … // ReplaceAttr is called to rewrite each non-group attribute before it is logged. // The attribute's value has been resolved (see [Value.Resolve]). // If ReplaceAttr returns a zero Attr, the attribute is discarded. // // The built-in attributes with keys "time", "level", "source", and "msg" // are passed to this function, except that time is omitted // if zero, and source is omitted if AddSource is false.


Handler level

Each handler has an optional Level value, which controls which logs to drop, and which to actually log: type HandlerOptions type HandlerOptions struct { … // Level reports the minimum record level that will be logged. // The handler discards records with lower levels. // If Level is nil, the handler assumes LevelInfo. // The handler calls Level.Level for each record processed; // to adjust the minimum level dynamically, use a LevelVar.

Get daily content like this in your inbox!

Subscribe