在Go语言中,高效并发获取游戏信息并优雅处理超时可以通过使用goroutine
、channel
和context
来实现。以下是一个示例代码,展示了如何实现这一目标。
goroutine
并发获取游戏信息我们可以为每个游戏信息请求启动一个goroutine
,这样可以并发地获取多个游戏的信息。
channel
传递结果每个goroutine
将获取到的游戏信息通过channel
传递回主goroutine
。
context
处理超时通过context
设置超时时间,确保在指定时间内获取到所有游戏信息,否则取消未完成的请求。
package main
import (
"context"
"fmt"
"math/rand"
"sync"
"time"
)
// 模拟获取游戏信息的函数
func fetchGameInfo(ctx context.Context, gameID int, resultChan chan<- string, wg *sync.WaitGroup) {
defer wg.Done()
// 模拟网络延迟
delay := time.Duration(rand.Intn(500)) * time.Millisecond
select {
case <-time.After(delay):
resultChan <- fmt.Sprintf("Game %d info fetched", gameID)
case <-ctx.Done():
// 如果超时或被取消,返回错误信息
resultChan <- fmt.Sprintf("Game %d fetch timeout or canceled", gameID)
}
}
func main() {
// 创建一个带有超时的context
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond)
defer cancel()
// 创建一个channel用于接收结果
resultChan := make(chan string, 10)
// 使用WaitGroup等待所有goroutine完成
var wg sync.WaitGroup
// 模拟并发获取多个游戏信息
gameIDs := []int{1, 2, 3, 4, 5}
for _, id := range gameIDs {
wg.Add(1)
go fetchGameInfo(ctx, id, resultChan, &wg)
}
// 启动一个goroutine等待所有fetchGameInfo完成
go func() {
wg.Wait()
close(resultChan)
}()
// 从resultChan中读取结果
for result := range resultChan {
fmt.Println(result)
}
}
fetchGameInfo
函数:模拟获取游戏信息的操作,通过time.After
模拟网络延迟。如果超时或被取消,则返回相应的错误信息。
context.WithTimeout
:创建一个带有超时的context
,超时时间为300毫秒。如果在超时时间内没有完成所有请求,context
会自动取消未完成的请求。
resultChan
:用于接收每个goroutine
返回的结果。使用buffered channel
以避免阻塞。
sync.WaitGroup
:用于等待所有goroutine
完成。在goroutine
完成时调用wg.Done()
,主goroutine
通过wg.Wait()
等待所有goroutine
完成。
close(resultChan)
:在所有goroutine
完成后关闭resultChan
,以便主goroutine
可以退出for range
循环。
由于fetchGameInfo
中模拟了随机延迟,每次运行的结果可能不同。部分结果可能因超时而返回错误信息。
Game 1 info fetched
Game 2 fetch timeout or canceled
Game 3 info fetched
Game 4 fetch timeout or canceled
Game 5 info fetched
通过使用goroutine
、channel
和context
,我们可以高效地并发获取游戏信息,并优雅地处理超时问题。这种方法适用于需要并发处理多个任务的场景,确保在指定时间内完成任务或及时取消未完成的任务。