How to Add a Timeout to an Infinite Loop in Go

This guide shows how to protect a long‑running Go function that checks a RabbitMQ cluster by using time.After and a select statement to automatically stop the infinite loop after a configurable timeout, improving robustness and maintainability.

Ops Development & AI Practice
Ops Development & AI Practice
Ops Development & AI Practice
How to Add a Timeout to an Infinite Loop in Go

When developing Go applications that perform continuous checks or polling, it is often necessary to prevent an infinite loop from running indefinitely. This article demonstrates how to add a timeout to such loops, using a RabbitMQ cluster‑checking example that should stop after three minutes.

Problem Description

The original function checkRabbitmqClusterIfForgetNode runs an endless for loop to execute a Docker command that queries the RabbitMQ cluster status. The requirement is to abort the loop automatically if it runs longer than three minutes.

Original Code

func checkRabbitmqClusterIfForgetNode(node string) bool {
    for {
        cmd := fmt.Sprintf("docker exec -i pam_pam-rabbitmq_1 rabbitmqctl --node %s cluster_status --formatter json", node)
        res, err := common.ExecuteCommandWithoutSpace("bash", "-c", cmd)
        if err != nil {
            log.Errorf("exec cmd %v failed, response: %v error: %v", cmd, res, err)
            continue
        }
        cluster, err := mq.ParseJSON(res)
        if err != nil {
            log.Errorf("parse json %v error: %v", res, err)
            continue
        }
        if nodes := cluster.CountDiskNodes(); nodes == 2 {
            log.Infof("rabbitmq cluster node number is %v, still not forget", nodes)
            continue
        }
        return true
    }
}

Adding a Timeout

Go’s time package provides time.After, which returns a channel that receives the current time after a specified duration. By creating a timeout channel and using a select statement inside the loop, the code can react to either the timeout event or the normal execution path.

Improved Code

func checkRabbitmqClusterIfForgetNode(node string) bool {
    timeout := time.After(3 * time.Minute) // set timeout to 3 minutes
    for {
        select {
        case <-timeout:
            log.Info("Operation timed out")
            return false // exit after timeout
        default:
            cmd := fmt.Sprintf("docker exec -i pam_pam-rabbitmq_1 rabbitmqctl --node %s cluster_status --formatter json", node)
            res, err := common.ExecuteCommandWithoutSpace("bash", "-c", cmd)
            if err != nil {
                log.Errorf("exec cmd %v failed, response: %v error: %v", cmd, res, err)
                continue
            }
            cluster, err := mq.ParseJSON(res)
            if err != nil {
                log.Errorf("parse json %v error: %v", res, err)
                continue
            }
            if nodes := cluster.CountDiskNodes(); nodes == 2 {
                log.Infof("rabbitmq cluster node number is %v, still not forget", nodes)
                continue
            }
            return true
        }
    }
}

The select statement waits on the timeout channel. When the three‑minute limit is reached, the timeout case fires, a log entry is written, and the function returns false, terminating the loop. If the timeout has not occurred, the default branch executes the original RabbitMQ check logic.

Conclusion

Using time.After together with a select statement provides a simple and effective way to bound the execution time of potentially endless Go loops. This pattern improves program robustness, prevents uncontrolled resource consumption, and makes long‑running background tasks easier to maintain.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendGolangselectTimeoutinfinite looptime.After
Ops Development & AI Practice
Written by

Ops Development & AI Practice

DevSecOps engineer sharing experiences and insights on AI, Web3, and Claude code development. Aims to help solve technical challenges, improve development efficiency, and grow through community interaction. Feel free to comment and discuss.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.