Skip to main content

Overview

keys — structured string keys for Go

keys is a small Go helper for building structured string keys from a base name plus optional segments.

It is useful when you want consistent names such as:

  • auth.user.not_found
  • http.request.id
  • db.query.duration_ms
  • service.timeout.read

The library keeps this simple:

  • keys.New(...) builds a single key.
  • keys.WithSegments(...) prepends one or more segments.
  • keys.WithSeparator(...) overrides the default . separator.
  • keys.Factory(...) creates a reusable constructor for keys that share the same prefix.

Empty segments are skipped automatically. If both the base name and all segments are empty, the result is an empty key.


Quick start

package main

import (
"fmt"

"github.com/ygrebnov/keys"
)

func main() {
key := keys.New("id", keys.WithSegments("http", "request"))
fmt.Println(key)

metricKey := keys.New(
"duration_ms",
keys.WithSegments("db", "query"),
keys.WithSeparator('_'),
)
fmt.Println(metricKey)

userKey := keys.Factory(keys.WithSegments("user"))
fmt.Println(userKey("email"))

// Output:
// http.request.id
// db_query_duration_ms
// user.email
}

Why use it?

  • Consistent naming across logs, metrics, tracing, config, and error identifiers.
  • Tiny API surface that is easy to remember.
  • Reusable factories for subsystem-specific prefixes.
  • Configurable separators when dot notation is not the right fit.

Core concepts

New

Use keys.New(name, opts...) to build a single key.

key := keys.New("field", keys.WithSegments("one", "two"))
fmt.Println(key) // one.two.field

WithSegments

Use keys.WithSegments(...) to prepend segments before the base name.

key := keys.New("not_found", keys.WithSegments("auth", "user"))
fmt.Println(key) // auth.user.not_found

WithSeparator

By default, keys uses .. Override it when another naming convention fits better.

key := keys.New("timeout", keys.WithSegments("service", "read"), keys.WithSeparator('_'))
fmt.Println(key) // service_read_timeout

Factory

Use keys.Factory(...) when many keys share the same prefix.

userKey := keys.Factory(keys.WithSegments("user"))

fmt.Println(userKey("id"))
fmt.Println(userKey("email"))

// Output:
// user.id
// user.email

Typical use cases

  • Structured error keys: auth.user.not_found — a natural fit for the companion errorc library.
  • Logging field names: http.request.id
  • Metrics and tracing attributes: db.query.duration_ms
  • Configuration namespaces: service.timeout.read

Notes

  • The default separator is ..
  • Empty segments are ignored.
  • If the name is empty and all segments are empty, the resulting key is empty.
  • The library requires Go 1.22 or later.

See Installation, Examples, and the companion errorc project for more.