geektutu/7days-golang · error

nil Getter

Error message

nil Getter

What it means

NewGroup panics with "nil Getter" when the getter argument is nil. The Getter is the mandatory cache-miss callback that fetches values from the source of truth (DB, file, etc.), so a Group without one can never resolve a miss; the library fails fast at construction instead of returning an error later. This is a deliberate programming-error panic, not a runtime failure.

Source

Thrown at gee-cache/day3-http-server/geecache/geecache.go:37

}

// A GetterFunc implements Getter with a function.
type GetterFunc func(key string) ([]byte, error)

// Get implements Getter interface function
func (f GetterFunc) Get(key string) ([]byte, error) {
	return f(key)
}

var (
	mu     sync.RWMutex
	groups = make(map[string]*Group)
)

// NewGroup create a new instance of Group
func NewGroup(name string, cacheBytes int64, getter Getter) *Group {
	if getter == nil {
		panic("nil Getter")
	}
	mu.Lock()
	defer mu.Unlock()
	g := &Group{
		name:      name,
		getter:    getter,
		mainCache: cache{cacheBytes: cacheBytes},
	}
	groups[name] = g
	return g
}

// GetGroup returns the named group previously created with NewGroup, or
// nil if there's no such group.
func GetGroup(name string) *Group {
	mu.RLock()
	g := groups[name]
	mu.RUnlock()

View on GitHub (pinned to cf36443821)

Solutions

  1. Pass a non-nil Getter implementation (e.g. a function wrapped with geecache.GetterFunc) to NewGroup
  2. Check the code that produces the Getter — ensure it never returns a typed-nil interface value
  3. If fetching from a DB, define a GetterFunc closure that loads the value, even if it just returns an error

Example fix

// before
var getter geecache.Getter
 g := geecache.NewGroup("scores", 2<<20, getter) // panics: nil Getter
// after
g := geecache.NewGroup("scores", 2<<20, geecache.GetterFunc(func(key string) ([]byte, error) {
    return loadFromDB(key)
}))
Defensive patterns

Strategy: validation

Validate before calling

if getter == nil {
    // fail before calling NewGroup, or supply a default
    panic("NewGroup requires a non-nil Getter")
}
g := geecache.NewGroup("scores", 2<<20, getter)

Type guard

func hasGetter(g geecache.Getter) bool {
    return g != nil // beware typed-nil: also assert the underlying value
}

Try / catch

// Go panics are not for control flow; use recover only at top level:
func safeNewGroup(name string, bytes int64, getter geecache.Getter) (g *geecache.Group) {
    defer func() {
        if r := recover(); r == "nil Getter" {
            g = geecache.NewGroup(name, bytes, geecache.GetterFunc(func(string) ([]byte, error) {
                return nil, errors.New("no loader configured")
            }))
        }
    }()
    return geecache.NewGroup(name, bytes, getter)
}

Prevention

When it happens

Trigger: Calling geecache.NewGroup(name, cacheBytes, nil) — e.g. passing an uninitialized Getter variable, a nil interface from a failed constructor of the real loader, or forgetting the argument entirely.

Common situations: Wiring a cache before the database layer is initialized; a factory function returning a typed-nil Getter interface; refactoring code so the getter variable is shadowed or zero-valued.

Related errors


AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03). Data as JSON: /api/errors/ed9039dfe6bb8aeb. Report an issue: GitHub.