go context上下文取消

package main

import (
	"context"
	"fmt"
	"sync"
	"errors"
	"time"
)

func Rpc(ctx context.Context, url string, isSuccess bool) error {
	result := make(chan int)
	err := make(chan error)

	if url == "http://rpc_2_url" {
		time.Sleep(time.Second * 5)
	}
	if url == "http://rpc_4_url" {
		time.Sleep(time.Second * 30)
	}
	go func() {
		// 进行RPC调用,并且返回是否成功,成功通过result传递成功信息,错误通过error传递错误信息
		if isSuccess {
			result <- 1
		} else {
			err <- errors.New("some error happen")
		}
	}()

	select {
	case <-ctx.Done():
		// 其他RPC调用调用失败
		fmt.Println("ctx.Done")
		return ctx.Err()
	case e := <-err:
		// 本RPC调用失败,返回错误信息
		fmt.Println("err", url, e)
		return e
	case <-result:
		fmt.Println("result", url, result)
		// 本RPC调用成功,不返回错误信息
		return nil
	}
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())

	//RPC1调用
	err := Rpc(ctx, "http://rpc_1_url", true)
	if err != nil {
		fmt.Println("err11111", err)
		return
	}

	wg := sync.WaitGroup{}

	// RPC2调用
	wg.Add(1)
	go func() {
		defer wg.Done()
		err := Rpc(ctx, "http://rpc_2_url", true)
		if err != nil {
			fmt.Println("err2", err)
			cancel()
		}
	}()

	// RPC3调用
	wg.Add(1)
	go func() {
		defer wg.Done()
		err := Rpc(ctx, "http://rpc_3_url", false)
		if err != nil {
			fmt.Println("err3", err)
			cancel()
		}
	}()

	// RPC4调用
	wg.Add(1)
	go func() {
		defer wg.Done()
		err := Rpc(ctx, "http://rpc_4_url", true)
		if err != nil {
			fmt.Println("err4", err)
			fmt.Println("RPC4 取消")
			cancel()
		}
	}()

	wg.Wait()
}

  

posted on 2021-11-12 18:20  running-fly  阅读(84)  评论(0编辑  收藏  举报

导航