{"record":{"id":"ed9039dfe6bb8aeb","repo":"geektutu/7days-golang","slug":"nil-getter-ed9039","errorCode":null,"errorMessage":"nil Getter","messagePattern":"nil Getter","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gee-cache/day3-http-server/geecache/geecache.go","lineNumber":37,"sourceCode":"}\n\n// A GetterFunc implements Getter with a function.\ntype GetterFunc func(key string) ([]byte, error)\n\n// Get implements Getter interface function\nfunc (f GetterFunc) Get(key string) ([]byte, error) {\n\treturn f(key)\n}\n\nvar (\n\tmu     sync.RWMutex\n\tgroups = make(map[string]*Group)\n)\n\n// NewGroup create a new instance of Group\nfunc NewGroup(name string, cacheBytes int64, getter Getter) *Group {\n\tif getter == nil {\n\t\tpanic(\"nil Getter\")\n\t}\n\tmu.Lock()\n\tdefer mu.Unlock()\n\tg := &Group{\n\t\tname:      name,\n\t\tgetter:    getter,\n\t\tmainCache: cache{cacheBytes: cacheBytes},\n\t}\n\tgroups[name] = g\n\treturn g\n}\n\n// GetGroup returns the named group previously created with NewGroup, or\n// nil if there's no such group.\nfunc GetGroup(name string) *Group {\n\tmu.RLock()\n\tg := groups[name]\n\tmu.RUnlock()","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-cache/day3-http-server/geecache/geecache.go#L19-L55","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a non-nil Getter implementation (e.g. a function wrapped with geecache.GetterFunc) to NewGroup","Check the code that produces the Getter — ensure it never returns a typed-nil interface value","If fetching from a DB, define a GetterFunc closure that loads the value, even if it just returns an error"],"exampleFix":"// before\nvar getter geecache.Getter\n g := geecache.NewGroup(\"scores\", 2<<20, getter) // panics: nil Getter\n// after\ng := geecache.NewGroup(\"scores\", 2<<20, geecache.GetterFunc(func(key string) ([]byte, error) {\n    return loadFromDB(key)\n}))","handlingStrategy":"validation","validationCode":"if getter == nil {\n    // fail before calling NewGroup, or supply a default\n    panic(\"NewGroup requires a non-nil Getter\")\n}\ng := geecache.NewGroup(\"scores\", 2<<20, getter)","typeGuard":"func hasGetter(g geecache.Getter) bool {\n    return g != nil // beware typed-nil: also assert the underlying value\n}","tryCatchPattern":"// Go panics are not for control flow; use recover only at top level:\nfunc safeNewGroup(name string, bytes int64, getter geecache.Getter) (g *geecache.Group) {\n    defer func() {\n        if r := recover(); r == \"nil Getter\" {\n            g = geecache.NewGroup(name, bytes, geecache.GetterFunc(func(string) ([]byte, error) {\n                return nil, errors.New(\"no loader configured\")\n            }))\n        }\n    }()\n    return geecache.NewGroup(name, bytes, getter)\n}","preventionTips":["Always wrap plain fetch functions with geecache.GetterFunc instead of passing function values directly","Initialize data sources before constructing cache groups","Add a startup integration test that builds all groups with real getters"],"tags":["go","cache","panic","nil-pointer"],"backgroundTag":"nil-cache-getter","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}