Files
Kévin Dunglas 03c26eca02 refactor: hoist LoaderFunc to package-level var in phpheaders (#2053)
## Summary

Hoists the `otter.LoaderFunc` closure in `GetUnCommonHeader` to a
package-level `loader` var, so it is allocated once at init time instead
of being re-created on every call.

This is a minor cleanup — the previous code created a new `LoaderFunc`
closure each time `GetUnCommonHeader` was called. While otter's
cache-hit path is fast enough that this doesn't show a measurable
difference in end-to-end benchmarks, avoiding the repeated allocation is
strictly better.

## What changed

**Before** (closure created per call):
```go
func GetUnCommonHeader(ctx context.Context, key string) string {
    phpHeaderKey, err := headerKeyCache.Get(
        ctx,
        key,
        otter.LoaderFunc[string, string](func(_ context.Context, key string) (string, error) {
            return "HTTP_" + headerNameReplacer.Replace(strings.ToUpper(key)) + "\x00", nil
        }),
    )
    ...
}
```

**After** (closure allocated once):
```go
var loader = otter.LoaderFunc[string, string](func(_ context.Context, key string) (string, error) {
    return "HTTP_" + headerNameReplacer.Replace(strings.ToUpper(key)) + "\x00", nil
})

func GetUnCommonHeader(ctx context.Context, key string) string {
    phpHeaderKey, err := headerKeyCache.Get(ctx, key, loader)
    ...
}
```

## Benchmarks

Apple M1 Pro, 8 runs, `benchstat` comparison — no regressions, no extra
allocations:

| Benchmark | main | PR | vs base |
|---|---|---|---|
| HelloWorld | 41.81µ ± 2% | 42.75µ ± 5% | ~ (p=0.065) |
| ServerSuperGlobal | 73.36µ ± 2% | 74.20µ ± 3% | ~ (p=0.105) |
| UncommonHeaders | 69.03µ ± 3% | 68.71µ ± 1% | ~ (p=0.382) |

All results within noise. Zero change in allocations.
2026-03-10 19:07:32 +01:00

6.8 KiB