Omit Redundant Nil Check

ID

go.omit_redundant_nil_check

Severity

info

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Code Smell

Language

Go

Tags

CWE:1164, code-style, readability

Description

Reports a nil check that is made redundant by an adjacent len comparison on the same value. The len builtin is defined for nil slices, maps and channels — a nil one has length zero — so a guard like if x != nil && len(x) != 0 can drop the x != nil operand, and if x == nil || len(x) == 0 can drop the x == nil operand.

Rationale

Because len(nil) is 0 for a slice, map or channel, the length comparison already decides the nil case, and the explicit nil test adds nothing but noise. The check only fires when the length comparison is genuinely conclusive: with && it must be false at length zero (!= 0, > 0, >= 1, == 5, …​), and with || it must be true at length zero (== 0, ⇐ 0, < 2, …​). Comparisons that are not conclusive — len(x) >= 0 (always true) or x != nil && len(x) == 0 (non-nil but empty is a real distinction) — are left alone. A pointer to an array (*[N]T) is excluded because len dereferences it, making the nil test necessary, and an impure operand such as gen() != nil && len(gen()) != 0 is never flagged.

func fn(s []int) {
    if s != nil && len(s) != 0 { // FLAW — len(s) != 0 already implies s != nil
        // ...
    }
    if len(s) != 0 { // OK — the nil check was redundant
        // ...
    }
    if s != nil && len(s) == 0 { // OK — non-nil but empty is a meaningful case
        // ...
    }
}

Remediation

Drop the redundant nil operand and keep only the len comparison.