context使用场景

context使用场景

context在Go语言中有广泛的应用场景,特别是在处理并发、网络请求和超时控制等方面。下面是一些常见的context应用场景的详细介绍:

  1. 并发控制和协程管理:context可以用于在多个协程之间进行协调和控制。通过创建带有取消信号的Context,可以在一组协程中传播取消信号,使它们能够相互通信并相应地停止运行。这样可以避免无限等待或竞态条件等问题。
  2. 超时和取消操作:context可以设置超时时间或截止时间,以控制操作的执行时间。当操作耗时超过预定的时间时,可以自动取消相关的操作。这对于防止资源浪费、提高系统的稳定性和响应性非常有用。
  3. 请求跟踪和日志记录:通过将context与请求关联,可以在多个处理函数或方法中传递请求特定的值,如请求ID、用户身份信息等。这样可以方便地跟踪请求的处理过程,记录相关的日志和审计信息。
  4. 并发任务的取消和中止:当需要取消一组并发任务时,可以使用context的取消机制。通过创建带有取消信号的Context,并在需要取消操作时调用cancel函数,可以通知相关的协程停止正在进行的操作,释放资源并退出。
  5. 网络请求管理:在处理网络请求时,context可以用于控制请求的生命周期、超时和取消。通过将context与每个请求相关联,可以在请求的整个生命周期内传递请求特定的值,并在超时或取消时及时结束请求的处理。
  6. 连接池和资源管理:在使用连接池或其他共享资源时,可以使用context来控制资源的生命周期和回收。通过创建带有取消信号的Context,并在资源使用完毕后调用cancel函数,可以及时释放资源并避免资源泄露。
  7. 测试和模拟场景:在进行单元测试或模拟场景时,可以使用context来创建一个自定义的Context,以模拟不同的操作和情况。这样可以更好地控制测试的条件和行为,确保代码的正确性和鲁棒性。

并发控制例子:


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 is working\n", id)
			time.Sleep(1 * time.Second)

		}
	}
}
func TestCancel(t *testing.T) {
	parent := context.Background()
	ctx, cancelFunc := context.WithCancel(parent)
	for i := 0; i <= 3; i++ {
		go worker(ctx, i)
	}

	time.Sleep(30 * time.Second)
	cancelFunc()

	time.Sleep(1 * time.Minute)
	fmt.Println("Main goroutine stopped")
}

超时和取消例子:

func processRequest(ctx context.Context) {
	select {
	case <-ctx.Done():
		fmt.Println("Request canceled or timed out")
		return
	case <-time.After(2 * time.Second):
		fmt.Println("Request processed successfully")
	}
}
func TestTimeout(t *testing.T) {
	parent := context.Background()
	ctx, cancel := context.WithTimeout(parent, 1*time.Second)
	defer cancel()

	processRequest(ctx)
}

请求跟踪例子:

type key string

func handleRequest(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	requestID := ctx.Value(key("requestID")).(string)
	log.Printf("Received request with ID: %s\n", requestID)
	fmt.Fprintf(w, "Request ID: %s", requestID)
}

func TestHandle(t *testing.T) {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		requestID := "12345" // 模拟从请求中获取的请求ID
		ctx := context.WithValue(r.Context(), key("requestID"), requestID)
		handleRequest(ctx, w, r)
	})

	http.ListenAndServe(":8080", nil)
}

网络请求管理例子(设置http请求超时时间):


func makeRequest(ctx context.Context, client *http.Client, url string) error {
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		return err
	}

	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// 处理响应结果
	// ...

	return nil
}

func TestMakeRequest(t *testing.T) {
	client := &http.Client{}
	url := "https://api.example.com/data"

	parent := context.Background()
	ctx, cancel := context.WithTimeout(parent, 30*time.Second)
	defer cancel()

	err := makeRequest(ctx, client, url)
	if err != nil {
		fmt.Printf("Request failed: %v\n", err)
		return
	}

	fmt.Println("Request successful")
}

你可能感兴趣的:(goland,golang,开发语言,后端)