{"record":{"id":"f41c4b18cd6144d9","repo":"geektutu/7days-golang","slug":"nil-getter-f41c4b","errorCode":null,"errorMessage":"nil Getter","messagePattern":"nil Getter","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gee-cache/day5-multi-nodes/geecache/geecache.go","lineNumber":38,"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":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-cache/day5-multi-nodes/geecache/geecache.go#L20-L56","documentation":"Same \"nil Getter\" fast-fail as errors 90/92, in the day5-multi-nodes version: NewGroup panics when the getter parameter is nil. A Group cannot fetch values on cache miss without a Getter, so construction with nil is treated as a programming error.","triggerScenarios":"geecache.NewGroup(name, cacheBytes, nil) in multi-node setups — often when the getter is meant to come from a shared config/DB pool that was not initialized.","commonSituations":"Config loading order bugs where the cache group is built before its data source; typed-nil interface values from factory functions; copy-pasted group setup code with the getter left nil.","solutions":["Pass a non-nil Getter implementation to NewGroup","Ensure initialization order: data source first, then groups","Guard against typed-nil by asserting the concrete value is usable"],"exampleFix":"// before\nvar dbGetter geecache.Getter // never assigned\ngrp := geecache.NewGroup(\"scores\", 2<<20, dbGetter)\n// after\ndbGetter := geecache.GetterFunc(func(key string) ([]byte, error) {\n    return db.Get(key)\n})\ngrp := geecache.NewGroup(\"scores\", 2<<20, dbGetter)","handlingStrategy":"validation","validationCode":"if getter == nil {\n    panic(\"NewGroup requires a non-nil Getter\")\n}\ngrp := geecache.NewGroup(\"scores\", 2<<20, getter)","typeGuard":"func getterReady(g geecache.Getter) bool { return g != nil }","tryCatchPattern":"// Recover at the top of server startup:\ndefer func() {\n    if r := recover(); r != nil { log.Fatalf(\"cache init: %v\", r) }\n}()","preventionTips":["Assign the Getter at declaration time, never leave it declared-then-set-later","Check factory functions for typed-nil interface returns","Cover group construction in a smoke test that fails before serving traffic"],"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"}