Loading...
Loading...

Go Select Statement Tutorial

Select statements are Go's control structure for handling multiple channel operations. They allow a goroutine to wait on multiple communication operations simultaneously, similar to a switch statement but for channels.

1. Basic Select Statement

1.1 How Select Works

The select statement blocks until one of its cases can run, then executes that case. If multiple cases are ready, it chooses one at random.

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

    go func() { ch1 <- "from ch1" }()
    go func() { ch2 <- "from ch2" }()

    select {
    case msg1 := <-ch1:
        fmt.Println("Received", msg1)
    case msg2 := <-ch2:
        fmt.Println("Received", msg2)
    }
}

1.2 Key Characteristics

  • Blocks until at least one case can proceed
  • Executes exactly one case (random selection if multiple ready)
  • All channel operations are evaluated before selection

2. Non-Blocking Operations

2.1 Default Case

The default case makes select non-blocking, executing immediately if no other cases are ready.

func main() {
    messages := make(chan string)

    select {
    case msg := <-messages:
        fmt.Println("Received message:", msg)
    default:
        fmt.Println("No message received")
    }
}

2.2 Non-Blocking Send

Useful for attempting sends without blocking:

func main() {
    ch := make(chan int, 1)

    select {
    case ch <- 42:
        fmt.Println("Sent value")
    default:
        fmt.Println("No receiver ready")
    }
}

3. Timeout Patterns

3.1 Basic Timeout

Use time.After to implement timeouts in channel operations:

func main() {
    ch := make(chan string)

    select {
    case res := <-ch:
        fmt.Println(res)
    case <-time.After(1 * time.Second):
        fmt.Println("Timeout after 1 second")
    }
}

3.2 Periodic Checks

Combine with tickers for periodic operations:

func main() {
    ticker := time.NewTicker(500 * time.Millisecond)
    done := make(chan bool)

    go func() {
        for {
            select {
            case <-done:
                return
            case t := <-ticker.C:
                fmt.Println("Tick at", t)
            }
        }
    }()

    time.Sleep(2 * time.Second)
    ticker.Stop()
    done <- true
}

4. Advanced Patterns

4.1 Priority Select

Use nil channels to prioritize certain cases:

func main() {
    var highPriority chan string // nil
    lowPriority := make(chan string, 1)
    lowPriority <- "low priority message"

    select {
    case msg := <-highPriority:
        fmt.Println("High priority:", msg)
    case msg := <-lowPriority:
        fmt.Println("Low priority:", msg)
    default:
        fmt.Println("No messages")
    }
}

4.2 Multiple Channel Monitoring

Continuous monitoring of multiple channels:

func worker(input1, input2 <-chan int, done <-chan bool) {
    for {
        select {
        case n := <-input1:
            fmt.Println("From input1:", n)
        case n := <-input2:
            fmt.Println("From input2:", n)
        case <-done:
            fmt.Println("Done")
            return
        }
    }
}

5. Common Pitfalls

5.1 Deadlocks

Select blocks forever if no cases are ready and no default:

func main() {
    ch := make(chan int)
    select {
    case <-ch: // Blocks forever
    }
}

5.2 Unbalanced Cases

Ignoring some channels can lead to resource leaks:

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

    go func() {
        for i := 0; i < 10; i++ {
            ch2 <- i // Never received
        }
    }()

    select {
    case <-ch1: // Only listens to ch1
    }
}

6. Best Practices

6.1 Always Include Timeouts

Prevent goroutines from hanging indefinitely:

select {
case result := <-longOperation():
    // handle result
case <-time.After(5 * time.Second):
    // handle timeout
}

6.2 Use Context for Cancellation

Properly manage goroutine lifecycles:

func worker(ctx context.Context, ch <-chan int) {
    for {
        select {
        case n := <-ch:
            // process n
        case <-ctx.Done():
            return
        }
    }
}
0 Interaction
0 Views
Views
0 Likes
×
×
×
🍪 CookieConsent@Ptutorials:~

Welcome to Ptutorials

$ Allow cookies on this site ? (y/n)

top-home