Last modified: Jan 23, 2026 By Alexander Williams

Go Blank Identifier _ in Assignments Guide

Go is a simple and efficient language. It has strict rules. One rule is that you must use every variable you declare. This prevents clutter in your code.

But sometimes, you get values you do not need. A function might return an error you want to ignore. A loop might give an index you will not use. The blank identifier solves this.

The blank identifier is an underscore: _. It is a special placeholder. It lets you discard values during assignment. This keeps your code clean and compliant with Go's rules.

What is the Blank Identifier?

In Go, every variable must be used. If you declare a variable and do not use it, the compiler will give an error. This is good. It stops unused code from piling up.

However, there are valid cases to ignore a value. The blank identifier acts like a write-only variable. You can assign a value to it. The value is immediately discarded.

Think of it as a black hole for data. Values go in but are never seen again. This satisfies the compiler's requirement for handling all return values.

Discarding Function Return Values

Functions often return multiple values. A common pattern is to return a result and an error. Sometimes, you only care about the result.

You cannot just ignore the error variable. The compiler will complain. Use the blank identifier to accept the error value you do not need.


package main

import (
    "fmt"
    "strconv"
)

func main() {
    // strconv.Atoi returns (int, error)
    // We only want the integer, ignoring potential parse error for this example
    num, _ := strconv.Atoi("123")
    fmt.Println("The number is:", num)

    // Trying to ignore without _ would cause a compile error
    // value, err := strconv.Atoi("123") // err is unused
}

The number is: 123

Warning: Ignoring errors is often a bad practice. Only do this when you are sure an error cannot happen or is irrelevant. For critical operations, always handle errors properly.

This technique is also useful with maps. Checking for a key returns a value and a boolean. If you only need to know if the key exists, discard the value.

Ignoring Loop Index or Value

In a for loop, you often get an index and a value. If you only need the value, the index variable becomes unused. This is a perfect job for the blank identifier.


package main

import "fmt"

func main() {
    fruits := []string{"apple", "banana", "cherry"}

    // We only need the fruit name, not its index
    for _, fruit := range fruits {
        fmt.Println("Fruit:", fruit)
    }

    // We only need the index, not the value
    for i, _ := range fruits {
        fmt.Println("Index:", i)
    }
}

Fruit: apple
Fruit: banana
Fruit: cherry
Index: 0
Index: 1
Index: 2

This keeps your code clean. It clearly shows your intent. You are ignoring the index because you do not need it. Understanding Go Variable Scope in for Loops helps you manage these temporary variables better.

Importing Packages for Side Effects

Some packages are imported for their side effects, not their exports. A database driver might register itself when its init() function runs. You do not need to use any functions from the package directly.

To import such a package, use the blank identifier. It acts as the package name. This tells the compiler the import is intentional.


package main

import (
    "database/sql"
    _ "github.com/mattn/go-sqlite3" // Blank import for driver registration
    "fmt"
)

func main() {
    db, err := sql.Open("sqlite3", "./test.db")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    fmt.Println("Database connection opened via side-effect import.")
}

The go-sqlite3 package registers its driver with the database/sql package in its init(). We never call its functions directly. The blank identifier makes this clear.

Checking Interface Satisfaction

Sometimes you want to ensure a type implements an interface. You can do this at compile time with a type assertion to the blank identifier. If the type does not satisfy the interface, you get a clear error.


package main

type Writer interface {
    Write([]byte) (int, error)
}

type MyWriter struct{}

func (mw MyWriter) Write(data []byte) (int, error) {
    return len(data), nil
}

// Compile-time check: MyWriter implements Writer
var _ Writer = MyWriter{}
// If MyWriter didn't have Write, compilation would fail here.

func main() {
    // Program runs only if the check above passes
}

This is a clever trick. It uses a variable declaration that is never used. The variable's name is _, so it does not cause an unused variable error. The assignment happens at compile time, verifying the interface contract.

When Not to Use the Blank Identifier

The blank identifier is a tool. Use it wisely. Its main purpose is to satisfy the compiler in specific, justified cases.

Avoid using it to hide errors you should handle. Ignoring an error from a file operation or network call can cause bugs that are hard to find. Always handle errors from important operations.

Do not use it to ignore values that are part of your core logic. If a value has a name, it should be used. If you find yourself using _ often, reconsider your function design or variable usage. For more on managing variables, see Go Best Practices for Temporary Variables.

Also, be mindful of variable shadowing. Using _ correctly avoids creating new variables that might accidentally shadow others.

Conclusion

The blank identifier _ is a small but powerful part of Go. It helps you write clean code that follows the language's strict rules.

Use it to discard unneeded function return values. Use it to ignore loop indices or values. Use it to import packages for their side effects. Use it for compile-time interface checks.

Remember, it is not a way to silence the compiler carelessly. It is a deliberate statement that a value is intentionally unused. Use it to make your code's intent clearer and more professional.

Mastering small features like this is key to writing idiomatic Go. It shows you understand the language's philosophy of simplicity and explicit code.