Golang中如何运行指定时长的goroutine

Golang中如何运行指定时长的goroutine 我是 Go 语言的新手。我正在通过编写一个简单的工具来学习 Go,该工具通过并发发送请求来测试 URL 的性能。

我已经使用 waitgroupgo routines 实现了并发。但是,我无法让我的程序执行 t 时长。

NewTicker 每隔 t 秒发送一次请求。但我希望 goroutine 能运行 t 时长。

请问有什么见解吗?谢谢!

2 回复

我认为你需要的是 context.WithTimeout(t)。然后使用该上下文或由其派生的上下文来使请求过期。

func main() {
    fmt.Println("hello world")
}

更多关于Golang中如何运行指定时长的goroutine的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中运行指定时长的goroutine,可以使用context.WithTimeouttime.After。以下是两种实现方式:

1. 使用context.WithTimeout(推荐)

package main

import (
    "context"
    "fmt"
    "time"
)

func worker(ctx context.Context, id int) {
    for {
        select {
        case <-ctx.Done():
            fmt.Printf("Worker %d stopped\n", id)
            return
        default:
            // 执行你的请求逻辑
            fmt.Printf("Worker %d sending request...\n", id)
            time.Sleep(500 * time.Millisecond) // 模拟请求
        }
    }
}

func main() {
    duration := 5 * time.Second // 指定运行时长
    ctx, cancel := context.WithTimeout(context.Background(), duration)
    defer cancel()

    // 启动多个goroutine
    for i := 1; i <= 3; i++ {
        go worker(ctx, i)
    }

    // 等待指定时长
    <-ctx.Done()
    time.Sleep(100 * time.Millisecond) // 等待所有goroutine退出
    fmt.Println("All workers stopped")
}

2. 使用time.After

package main

import (
    "fmt"
    "sync"
    "time"
)

func worker(stopChan <-chan struct{}, id int, wg *sync.WaitGroup) {
    defer wg.Done()
    
    for {
        select {
        case <-stopChan:
            fmt.Printf("Worker %d stopped\n", id)
            return
        default:
            // 执行你的请求逻辑
            fmt.Printf("Worker %d sending request...\n", id)
            time.Sleep(500 * time.Millisecond) // 模拟请求
        }
    }
}

func main() {
    duration := 5 * time.Second // 指定运行时长
    stopChan := make(chan struct{})
    var wg sync.WaitGroup

    // 启动多个goroutine
    for i := 1; i <= 3; i++ {
        wg.Add(1)
        go worker(stopChan, i, &wg)
    }

    // 设置超时
    time.AfterFunc(duration, func() {
        close(stopChan)
    })

    wg.Wait()
    fmt.Println("All workers stopped")
}

3. 针对你的URL测试工具的具体实现

func testURLs(duration time.Duration, urls []string) {
    ctx, cancel := context.WithTimeout(context.Background(), duration)
    defer cancel()
    
    var wg sync.WaitGroup
    results := make(chan string, len(urls))
    
    for _, url := range urls {
        wg.Add(1)
        go func(u string) {
            defer wg.Done()
            for {
                select {
                case <-ctx.Done():
                    return
                default:
                    // 发送HTTP请求
                    start := time.Now()
                    resp, err := http.Get(u)
                    latency := time.Since(start)
                    
                    if err != nil {
                        results <- fmt.Sprintf("%s: error - %v", u, err)
                    } else {
                        results <- fmt.Sprintf("%s: %s - latency: %v", 
                            u, resp.Status, latency)
                        resp.Body.Close()
                    }
                    
                    time.Sleep(100 * time.Millisecond) // 请求间隔
                }
            }
        }(url)
    }
    
    // 收集结果
    go func() {
        wg.Wait()
        close(results)
    }()
    
    for result := range results {
        fmt.Println(result)
    }
}

第一种方法使用context更符合Go的并发模式,能更好地控制goroutine的生命周期。第二种方法使用channel也能达到相同效果。两种方法都能确保goroutine在指定时长后停止执行。

回到顶部