Excessive nil pointer checks in Go
Jun 16, 2026
Let’s talk about nil pointer checks in Go. You want to prevent panics in production, but that doesn’t start with a deferred recover . It starts with defensive programming. Check your inputs, check your bounds, and check pointers for nil before dereferencing them.
I’ve started to see more nil checks in Go code. In the right place, they are necessary for writing safe code. In the wrong place, they are a sign that the code has stopped being clear about what can and cannot be nil. I have noticed this pattern more in generated code, but this symptom is not new and is not limited to AI.
When a nil check is cheap and prevents a panic, why not add it? Your reflex may be, let’s just be safe. But the check also tells the next reader something, and often the wrong thing.
Nil Check on a Dependency
Consider a nil check on a dependency. A type RateLimiter holds a Redis client, and a nil check guards before using it in lines 10 to 12:
1 type RateLimiter struct { 2 redis * redis . Client 3 } 4 5 func ( r * RateLimiter ) Allow ( ctx context . Context , req * Request ) ( bool , error ) { 6 userID := GetUserID ( req ) 7 if userID == "" { 8 return false , nil 9 } 10 if r . redis != nil { 11 return r . checkLimit ( ctx , userID ) 12 } 13 return false , nil 14 }
At a glance, it looks like the safe thing to do, but you should ask yourself: why would you construct RateLimiter with a nil dependency?
If the Redis client is nil, the error happened earlier, at construction time. Checking for it now does not handle that error. Worse, it treats operating with the failed construction as an acceptable state. In Go, you want to fail fast and fail early.
... continue reading