面试题答案
一键面试以下以Go语言为例:
package main
import (
"context"
"fmt"
"net/http"
"time"
)
// 模拟从后端服务获取数据的函数
func fetchData(ctx context.Context, url string) (string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return "", err
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
// 这里简单返回URL,实际应该读取响应体
return url, nil
}
func main() {
// 创建一个带有取消功能的上下文
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
urls := []string{
"http://example.com/api1",
"http://example.com/api2",
"http://example.com/api3",
}
var results []string
var errs []error
var semaphore = make(chan struct{}, 3) // 限制并发数
for _, url := range urls {
semaphore <- struct{}{}
go func(u string) {
defer func() { <-semaphore }()
data, err := fetchData(ctx, u)
if err != nil {
errs = append(errs, err)
} else {
results = append(results, data)
}
}(url)
}
// 等待所有请求完成
for i := 0; i < len(urls); i++ {
semaphore <- struct{}{}
}
for i := 0; i < len(urls); i++ {
<-semaphore
}
if len(errs) > 0 {
fmt.Println("Errors:", errs)
} else {
fmt.Println("Results:", results)
}
}
- 上下文创建:
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
创建了一个带有超时(2秒)的上下文,defer cancel()
确保在函数结束时取消上下文,释放相关资源。 - 请求取消控制:
http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
将上下文附加到HTTP请求中,如果上下文被取消(例如超时),HTTP请求也会被取消。 - 资源管理:
- 使用
defer resp.Body.Close()
关闭HTTP响应的Body,避免资源泄漏。 - 使用信号量
semaphore
控制并发数,避免同时发起过多请求导致资源耗尽。
- 使用