How to cancel goroutines after a certain amount of time

I am making a load testing tool that makes multiple HTTP calls to goroutines and it works, but now I am trying to only allow it to run for a certain duration.

How can I cancel goroutines when sleep is over?

I am currently trying to make a goroutine that executes time.Sleep()

for the duration specified and when that is complete it will broadcast a message to the channel.

In my endless loop, I listen to the message in the switch statement, and when it's there, I come back. This works the way I want.

The problem is goroutines from the string go httpPost()

will keep making HTTP calls. I even try to pipe a pipe to this function and listen to the same message there CALL_TIME_RAN_OUT

, but for whatever reason, when I do this, the goroutines only run once and then return immediately, as opposed to waiting for the message to be broadcast to the end Sleep


Does anyone know a better approach I can take? It doesn't seem to work.

Here's the code (removed irrelevant parts):

func attack(cfg AttackConfig) {
    // some code ...

    var ar attackResponse
    ch := make(chan uint8, 8)

    go func() {
        time.Sleep(cfg.Duration * time.Second)
        ch <- CALL_TIME_RAN_OUT

    for {
        if atomic.LoadInt32(&currConnections) < atomic.LoadInt32(&maxConnections) - 1 {
            go httpPost(cfg, &ar, ch)

        switch <-ch {
        // some other cases ...
        case CALL_TIME_RAN_OUT:
            fmt.Printf("%d seconds have elapsed. Shutting down!", cfg.Duration)

func httpPost(cfg AttackConfig, a *attackResponse, ch chan uint8) {
    // some code here to create HTTP client ...

    for {
        // some code to make HTTP call ...

        switch <-ch {
        case CALL_TIME_RAN_OUT:



source to share

1 answer

use the package

. Go 1.7 moves the package

to the standard library as context

. So it's easy import context

if you are using version 1.7+.

usage is simple:

package main

import (

func test(ctx context.Context) {
    t := time.Now()

    select {
    case <-time.After(1 * time.Second):
    case <-ctx.Done():
    fmt.Println("used:", time.Since(t))

func main() {
    ctx, _ := context.WithTimeout(context.Background(), 50*time.Millisecond)




All Articles