codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
🐹

Go (Golang)

20 / 72 topics
17Concurrency Basics18Goroutines19Channels20Select Statement21Sync Package
Tutorials/Go (Golang)/Select Statement
🐹Go (Golang)

Select Statement

Updated 2026-05-15
10 min read

Select Statement

Introduction

In Go, the select statement is a powerful feature that allows you to handle multiple communication operations on channels. It enables your program to wait for multiple channel events and execute code based on which event occurs first. This is particularly useful in concurrent programming where you need to manage multiple goroutines and their interactions.

The select statement works similarly to a switch, but instead of comparing values, it compares the communication operations with the channels' states. It blocks until one of the cases can proceed, or if there's no case that can proceed, it will block indefinitely unless a default case is provided.

Concept

The basic syntax for a select statement is as follows:

select {
case channel1 <- value:
    // code to execute when sending to channel1 succeeds
case value := <-channel2:
    // code to execute when receiving from channel2 succeeds
default:
    // code to execute if no other case can proceed
}

Each `case` in a `select` statement corresponds to either a send or receive operation on a channel. The `select` statement waits for any of the cases to be ready, and then executes the corresponding block of code.

- **Send Cases**: If a case is sending a value to a channel (`channel1 <- value`), it will proceed if there is a receiver waiting for that channel.
- **Receive Cases**: If a case is receiving from a channel (`value := <-channel2`), it will proceed if there is a sender ready to send on that channel.

The `default` case, if present, allows the `select` statement to execute without blocking. It is useful when you want to avoid blocking indefinitely and handle scenarios where none of the channels are ready.

## Examples

### Basic Select Statement

Let's start with a simple example where we have two channels and use a `select` statement to handle operations on them.

```go
package main

import (
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)

    go func() {
        time.Sleep(1 * time.Second)
        ch1 <- "One"
    }()

    go func() {
        time.Sleep(2 * time.Second)
        ch2 <- "Two"
    }()

    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-ch1:
            fmt.Println("Received", msg1)
        case msg2 := <-ch2:
            fmt.Println("Received", msg2)
        }
    }
}

In this example, two goroutines send messages to `ch1` and `ch2` after different durations. The `select` statement in the main function waits for either channel to be ready to receive a message. It prints the received message and continues until both messages are processed.

### Select with Default Case

Now, let's modify the previous example to include a `default` case, which will execute if neither of the channels is ready.

```go
package main

import (
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)

    go func() {
        time.Sleep(3 * time.Second)
        ch1 <- "One"
    }()

    go func() {
        time.Sleep(4 * time.Second)
        ch2 <- "Two"
    }()

    for i := 0; i < 5; i++ {
        select {
        case msg1 := <-ch1:
            fmt.Println("Received", msg1)
        case msg2 := <-ch2:
            fmt.Println("Received", msg2)
        default:
            fmt.Println("No message received")
        }
        time.Sleep(1 * time.Second)
    }
}

In this modified version, the `select` statement includes a `default` case. If neither channel is ready to receive a message within one second, it prints "No message received". This prevents the program from blocking indefinitely.

### Select with Multiple Receives

You can also use multiple receive cases in a single `select` statement. Here's an example:

```go
package main

import (
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)

    go func() {
        time.Sleep(1 * time.Second)
        ch1 <- "One"
    }()

    go func() {
        time.Sleep(1 * time.Second)
        ch2 <- "Two"
    }()

    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-ch1:
            fmt.Println("Received from ch1:", msg1)
        case msg2 := <-ch2:
            fmt.Println("Received from ch2:", msg2)
        }
    }
}

In this example, both goroutines send messages to ch1 and ch2 after the same duration. The select statement handles both receive operations simultaneously. Since both channels are ready at the same time, the order of execution is non-deterministic.

What's Next?

Now that you understand how to use the select statement in Go, it's important to be aware of potential errors and edge cases. In the next section, we will explore common pitfalls and best practices when working with channels and select.

Stay tuned for more advanced topics on Go programming!


PreviousChannelsNext Sync Package

Recommended Gear

ChannelsSync Package