最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

VS Code incorrectly giving unreachable code (go for-select channel block) - Stack Overflow

programmeradmin1浏览0评论

I have a for loop that needs to run indefinitely that has a nested loop to consume all items in a channel without waiting for the channel to close. VS Code is giving me an unreachable code error for the following Go code:

errCh := make(chan error, 5)

for {
    log.Print("do stuff")

    for {
        select {
        case err := <-errCh:
            log.Printf("error occured: %s", err)
        default:
            break
        }
    }

    time.Sleep(1 * time.Second)
}

VS Code is telling me that the sleep line is unreachable, I'm guessing because it thinks that the break statement exits the outer for loop, although I am 99% sure that break only exits the inner for loop. Can I safely ignore this, or does VS Code know something that I don't?

Alternatively, I considered doing something like this:

errCh := make(chan error, 5)

go func() {
    for err := range errCh {
        log.Printf("Error occurred: %s", err)
    }
}()

for {
    log.Print("do stuff")

    time.Sleep(1 * time.Second)
}

Would this be more idiomatic?

I have a for loop that needs to run indefinitely that has a nested loop to consume all items in a channel without waiting for the channel to close. VS Code is giving me an unreachable code error for the following Go code:

errCh := make(chan error, 5)

for {
    log.Print("do stuff")

    for {
        select {
        case err := <-errCh:
            log.Printf("error occured: %s", err)
        default:
            break
        }
    }

    time.Sleep(1 * time.Second)
}

VS Code is telling me that the sleep line is unreachable, I'm guessing because it thinks that the break statement exits the outer for loop, although I am 99% sure that break only exits the inner for loop. Can I safely ignore this, or does VS Code know something that I don't?

Alternatively, I considered doing something like this:

errCh := make(chan error, 5)

go func() {
    for err := range errCh {
        log.Printf("Error occurred: %s", err)
    }
}()

for {
    log.Print("do stuff")

    time.Sleep(1 * time.Second)
}

Would this be more idiomatic?

Share Improve this question edited Jan 30 at 16:27 Xela asked Jan 30 at 16:19 XelaXela 1191 silver badge10 bronze badges 2
  • 5 First solution is wrong, because the break would only exit the select statement and the inner for-loop will never exit, making the sleep unreachable. 2nd is fine, assuming you plan to act, when you get an err value on the channel i.e. exit after n errors or something - tip.golang./ref/spec#Break_statements – Inian Commented Jan 30 at 16:30
  • 1 @Inian ahh, silly me, thank you! Happy to give an accepted answer if you want to post answer? – Xela Commented Jan 30 at 16:36
Add a comment  | 

1 Answer 1

Reset to default -3

You're correct that break only exits the inner for loop, but there's an issue with how you're trying to drain the channel inside the nested loop. The problem arises because break in a select block only breaks out of the select, not the loop itself. However, your default case immediately triggers when errCh is empty, causing the inner loop to exit every time it's evaluated.

Recommended Approach

Your second approach is far more idiomatic and preferred in Go. The issue with the first approach is that it tightly couples draining errCh with the main loop logic, making it harder to read and manage. The second approach correctly offloads error handling into a separate goroutine, ensuring that errors are processed asynchronously while your main loop continues executing.

  • Benefits of the second approach:

    • Concurrency – The error-handling goroutine runs independently of the main loop, ensuring errors are processed as they arrive.
    • Separation of Concerns – The main loop isn't cluttered with error-draining logic.
    • Scalability – If the error channel receives a large number of errors quickly, the separate goroutine can handle them more efficiently than a single-threaded loop.
  • Additional Notes

    • Since errCh is unbounded in time (i.e., there's no plan to close it in your example), the for err := range errCh goroutine will run indefinitely. Ensure there is a mechanism to close errCh if needed.
    • If errCh has a high throughput and needs rate-limiting or buffering, you might consider using a worker pool pattern.
发布评论

评论列表(0)

  1. 暂无评论