Gob cache encoder
Generic Gob encoder implementing cache.EncoderPort[V] for any value type, registers with a cache.EncodingRegistry to handle the cache write/read serialisation step.
Overview
The Gob encoder turns Go values into bytes using encoding/gob, Go's binary format from the standard library. Gob carries Go type information across the wire and emits compact output for nested struct types. It also encodes concrete types behind interface fields once you register them with gob.Register. For Go-to-Go cache traffic it targets smaller, faster serialisation than JSON. The trade-off is that only Go can read Gob output, you cannot inspect a cached value with redis-cli, and a Python service cannot read a Gob-encoded cache entry.
Reach for Gob when only Go services read and write the cache. It also fits when payloads are large enough that JSON's verbosity hurts. Or when the value types contain Go-specific shapes (interfaces, embedded structs) that round-trip awkwardly through JSON. Reach for JSON when cross-language compatibility, human readability, or schema documentation matter more than size.
The encoder is generic over a single value type V. Register one encoder per cached type, plus optionally a default encoder for the catch-all case. The constructor takes no configuration. New[V]() returns a ready encoder, so the only glue you write is the registration step.
Encoders do not register through piko.New(...). They go on a cache.EncodingRegistry that you then hand to the cache provider. Encoders matter only for serialising providers such as Redis and Valkey. In-memory providers, including Otter and a multi-level L1, hold live Go values and do not consume the encoding registry.
Configuration
import (
"context"
"piko.sh/piko/wdk/cache"
"piko.sh/piko/wdk/cache/cache_encoder_gob"
)
// Build a Gob encoder for a specific value type.
userEncoder := cache_encoder_gob.New[User]()
// Register it on a cache.EncodingRegistry. Pass nil as the default
// encoder if every cached type is registered explicitly.
registry := cache.NewEncodingRegistry(nil)
if err := registry.Register(ctx, userEncoder.(cache.AnyEncoder)); err != nil {
return err
}
New[V]() returns a typed cache.EncoderPort[V]. The registry stores type-agnostic encoders, so assert the result to cache.AnyEncoder when you register it or pass it as the default. The concrete encoder implements both interfaces, so the assertion holds at runtime.
Pass the registry to a cache provider via its Registry field (Redis, Valkey, and so on). To attach an encoder to a single cache builder namespace, use builder.TypedEncoder(encoder), which takes the cache.EncoderPort[V] directly without an assertion.
Bootstrap
There is no piko.With* registration for encoders, they attach to the cache through the provider's Registry field, or through the cache builder. A typical wiring uses Gob as the registry default while leaving room for type-specific encoders:
import (
"piko.sh/piko/wdk/cache"
"piko.sh/piko/wdk/cache/cache_encoder_gob"
"piko.sh/piko/wdk/cache/cache_provider_redis"
)
registry := cache.NewEncodingRegistry(cache_encoder_gob.New[any]().(cache.AnyEncoder))
provider, err := cache_provider_redis.NewRedisProvider(cache_provider_redis.Config{
Address: "localhost:6379",
Registry: registry,
})
Every encoder uses the same cache.EncoderPort[V] contract, so swapping Gob for JSON is a one-line change at the registry. Replace cache_encoder_gob.New with cache_encoder_json.New and the rest of the wiring stays the same.
Decode-size cap
Decoding enforces a default cap of 64 MiB on the gob payload. A stream larger than the cap fails with cache_encoder_gob.ErrGobInputTooLarge before allocating the declared buffer, which guards against allocation-bomb streams from poisoned cache contents. Use errors.Is to detect it.
Tune the cap with cache_encoder_gob.SetMaxGobInputBytes(maxBytes) and read the active value with cache_encoder_gob.MaxGobInputBytes(). A value of zero or below disables the cap, which is not recommended for attacker-influenced cache contents.
See also
Other cache encoders and transformers:
- JSON encoder, cross-language alternative.
- Crypto transformer, encrypt cached values after encoding.
- Zstd transformer, compress cached values after encoding.
Cache providers that consume the encoder registry:
- Redis, requires the
Registryfield. - Valkey, requires the
Registryfield. - Redis Cluster, requires the
Registryfield. - Valkey Cluster, requires the
Registryfield.
Framework docs:
- How to use the cache, wiring the cache service end-to-end.
- Cache API reference,
EncoderPort,EncodingRegistry, and the cache builder.
External:
- encoding/gob, standard library reference.