plugin

package
v0.1.40 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: MIT Imports: 1 Imported by: 0

README

plugin

The question a process-wide registry asks before it publishes anything — a kernel primitive (stdlib-only, no domain vocabulary).

func Register(c Codec) Codec {
    if why := plugin.Unusable(c); why != "" {
        panic(fmt.Sprintf("codec.Register [%s CODEC_NIL]: %s", CodeCodecNil, why))
    }
    …
}

Unusable returns the empty string for a value a registry can store, and a reason fragment for the two shapes that satisfy an interface at compile time and cannot serve one call:

  • a typed nil — (*gzipCompressor)(nil) is not == nil, so the usual guard lets it through and the failure surfaces at the first dispatch, far from the import that caused it;
  • a value whose type is not comparable — registries compare entries to tell an idempotent re-registration from a conflict, and == on such a value panics with Go's comparing uncomparable type instead of the registry's own duplicate error.

The reason is a fragment meant to follow a colon in the caller's message, so each registry keeps its own dotted-quad code and reason.

ADR 0071. See CLAUDE.md for why it returns a string rather than an error.

Documentation

Overview

Package plugin answers one question a process-wide registry must ask before it publishes anything: is this value usable as an entry at all?

A registry stores values behind an interface and hands them back to every caller for the life of the process. Two shapes satisfy such an interface at compile time and cannot serve:

  • a TYPED nil — (*gzipCompressor)(nil) is not == nil, so the guard every registrar writes lets it through, it is stored, and every lookup returns it. The failure surfaces at the first dispatch, arbitrarily far from the registration that caused it;
  • a value whose dynamic type is NOT COMPARABLE — a struct holding a slice, a map or a function. Registries compare entries to tell an idempotent re-registration from a conflict, and == on such a value is a runtime panic naming Go's comparison rather than the duplicate plug-in.

Both are programming errors at import time, which is why the answer is a reason string rather than an error: the registrar panics with its OWN dotted-quad code and reason, and only borrows the sentence that says why.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Unusable

func Unusable[T any](v T) string

Unusable reports why v cannot be published into a registry, or the empty string when it can. The reason is a fragment meant to follow a colon in the caller's own message, e.g. "nil *gzip.compressor".

It is deliberately not a predicate returning bool: a registrar that refuses must say which of the two shapes it refused, because "nil Compressor" and "Compressor is not comparable" are found by different searches and fixed in different places.

The parameter is a type PARAMETER rather than an `any`, which costs the caller nothing — every registrar passes its port and T is inferred — and keeps the signature from claiming to accept anything in particular. What is judged is the dynamic value either way: reflect sees through the boxing.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL