Skip to content
JavaGo
Part III · Functions & Errors

Blank Identifier

The underscore discards values on purpose: ignored results, side-effect imports, and compile-time interface checks.

Section 13 of 31 3 min read

Go refuses to compile unused imports and unused local variables. Java merely warns about them, if your IDE is configured to. The blank identifier _ is how you tell the compiler "I am discarding this on purpose". It can be assigned to, but never read.

Five uses of _

_ in five contexts
// 1. Discard one of several results (be deliberate about errors!)
n, _ := fmt.Sscan(input, &x)

// 2. Discard the index (or value) in a range loop
for _, msg := range messages {
    process(msg)
}

// 3. Import a package only for its side effects (its init functions)
import (
    _ "github.com/jackc/pgx/v5/stdlib" // registers the "pgx" database/sql driver
    _ "net/http/pprof"                 // registers /debug/pprof/ handlers
    _ "time/tzdata"                    // embeds the time zone database
)

// 4. Compile-time interface check (below)
var _ MessageStore = (*PostgresStore)(nil)

// 5. Keep a variable around while you are mid-refactor
_ = unusedForNow

The compile-time interface check

assert that a type satisfies an interface, at zero runtime cost
// Usually placed right below the type it checks
var (
    _ MessageStore  = (*PostgresStore)(nil)
    _ MessageBroker = (*RedisBroker)(nil)
    _ http.Handler  = (*Router)(nil)
)

// Read it as: "a nil *PostgresStore must be assignable to a
// MessageStore". If a method is missing or its signature drifts,
// the build fails HERE, with a precise message:
//
//   cannot use (*PostgresStore)(nil) (value of type *PostgresStore)
//   as MessageStore value in variable declaration:
//   *PostgresStore does not implement MessageStore
//   (missing method Delete)

n, _ := fmt.Sscan(input, &x)

var _ MessageStore = (*PostgresStore)(nil)

Fig. 13.1The blank identifier accepts a value and throws it away, which is how you tell the compiler a discard is deliberate. Declaring it with an interface type, as in var _ MessageStore = (*PostgresStore)(nil), makes the compiler check that *PostgresStore still satisfies MessageStore.
↑ ↓ to navigateEnter to openEsc to close