# Go While Loop vs Standard For Loop: Is There a Practical Difference?

> Discover the practical difference between Go's for loop and a for loop acting as a while loop. Learn when to use each for effective Go programming.

- Repository: [Go/go](https://github.com/golang/go)
- Tags: deep-dive
- Published: 2026-02-16

---

**Go treats condition-only for loops and traditional C-style for loops identically at the compiler level, making the choice purely stylistic with no performance impact.**

When writing Go code, you might wonder whether emulating a **go while loop** using `for condition` differs from the standard three-clause `for init; condition; post` syntax. According to the Go source code, both forms resolve to the same internal representation, meaning your decision should focus on readability and variable scoping rather than execution efficiency.

## The Three Syntactic Forms of Go For Loops

Go specification defines a single loop construct with three distinct syntax variations, all documented in [`doc/go_spec.html`](https://github.com/golang/go/blob/main/doc/go_spec.html).

### Condition-Only (While-Style)

The **go while loop** pattern uses only a boolean expression:

```go
i := 0
for i < 10 {
    fmt.Println(i)
    i++
}

```

This form repeats execution while the condition evaluates to `true`, functioning identically to while loops in other languages.

### Traditional For (Init; Condition; Post)

The C-style syntax keeps loop control explicit in the header:

```go
for i := 0; i < 10; i++ {
    fmt.Println(i)
}

```

This consolidates initialization, testing, and iteration into a single line.

### Range Loops

For iterating over collections:

```go
for index, value := range slice {
    fmt.Println(index, value)
}

```

## Compiler Implementation: Why There's No Difference

The Go compiler treats all three forms as the same underlying construct. In [`src/cmd/compile/internal/ir/stmt.go`](https://github.com/golang/go/blob/main/src/cmd/compile/internal/ir/stmt.go), the `ForStmt` structure represents every variant:

```go
type ForStmt struct {
    miniStmt
    Cond   Node   // condition (nil for infinite loops)
    Post   Node   // post statement (nil for condition-only)
    Body   Nodes  // loop body
    // ... other fields
}

```

Whether you write `for i := 0; i < n; i++` or `for i < n`, the compiler populates the same `ForStmt` fields—`Init` and `Post` simply remain nil in the condition-only case. The SSA generation phase produces identical machine code for both patterns, confirming **zero performance difference** between a go while loop and a standard for loop.

## Practical Guidelines for Choosing

Since the compiler generates identical output, base your decision on code clarity.

### Readability and Intent

Use the **condition-only form** when the loop behaves like a traditional while loop—when initialization happens naturally before the loop or when the update logic varies:

```go
scanner := bufio.NewScanner(file)
for scanner.Scan() {  // reads like "while scanner has tokens"
    process(scanner.Text())
}

```

Use the **three-clause form** when loop variables are introduced, tested, and incremented in a standard pattern:

```go
for i := 0; i < len(items); i++ {
    process(items[i])
}

```

### Variable Scoping Benefits

The init clause creates variables scoped strictly to the loop body. This prevents namespace pollution:

```go
for sum := 0; sum < 100; sum += 10 {
    fmt.Println(sum)
}
// `sum` is undefined here

```

With a go while loop style, you must declare variables outside the loop, extending their scope:

```go
sum := 0
for sum < 100 {
    fmt.Println(sum)
    sum += 10
}
// `sum` still exists here

```

### Infinite Loops

Both `for { }` and `for true { }` compile identically to an infinite loop. Prefer the shorter `for { }` form as it is idiomatic in Go.

## Summary

- Go provides one loop construct with three syntax variants, all represented by the same `ForStmt` AST node in [`src/cmd/compile/internal/ir/stmt.go`](https://github.com/golang/go/blob/main/src/cmd/compile/internal/ir/stmt.go).
- A **go while loop** (condition-only `for`) and a standard three-clause `for` loop generate identical machine code with no performance difference.
- Choose the condition-only form for while-like semantics and the three-clause form when you need scoped initialization and increment logic.
- Use `for { }` for infinite loops as the idiomatic shorthand.

## Frequently Asked Questions

### Is a Go while loop slower than a for loop?

No. The Go compiler treats `for condition { }` and `for init; condition; post { }` as identical constructs. Both resolve to the same `ForStmt` internal representation in [`src/cmd/compile/internal/ir/stmt.go`](https://github.com/golang/go/blob/main/src/cmd/compile/internal/ir/stmt.go) and produce the same optimized machine code during SSA generation.

### Can I use break and continue in condition-only for loops?

Yes. The `break` and `continue` statements work identically across all `for` loop variants. Since the compiler treats a go while loop as a standard `ForStmt`, control flow keywords function exactly as they do in three-clause or range loops.

### Why doesn't Go have a separate while keyword?

Go intentionally simplifies its syntax by providing a single loop construct that covers all use cases. The language designers chose to use `for` for all iteration patterns—condition-only, three-clause, and range—to reduce cognitive load and maintain consistency. This is documented in the language specification at [`doc/go_spec.html`](https://github.com/golang/go/blob/main/doc/go_spec.html).

### How do I create an infinite loop in Go?

Use `for { }` with no condition, which the compiler treats as an implicit `true` condition. This is the idiomatic Go equivalent of a `while(true)` loop in other languages. Both `for { }` and `for true { }` compile to identical bytecode, but the empty form is preferred by Go style guidelines.