Talk about the context of golang

The main purpose of golang context is to transfer data between multiple goroutines and manage the lifecycle of multiple goroutines. The actual application scenarios are, for example, in the http service, each request corresponds to a goroutine, and other APIs may be called in the request to generate more goroutines. It is more convenient to use context to manage these goroutines. Transfer data and management in these goroutine.

Main method

func Background() Context 

Background () returns an empty context, which is a root node.

func TODO() Context

TODO () returns an empty context. The difference between it and Background is the purpose. When you use a todo context, the code maintainer knows that the design intent at that time is pending.

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)

WithCancel () derives a child context with a cancel method, which is very useful when recursively manipulating the context.

func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)

WithDeadline () and WithTimeout () are not the same, except that the parameters passed by the two are different, one is the cut-off time, and the other is the time interval.

func WithValue(parent Context, key interface{}, val interface{}) Context

WithValue () can take some parameters in the context.

Principles of managing goroutine

After a brief understanding of the context method, let's explore why context can manage goroutine. First look at a small example:

func doSomething(ch chan int, id int) {
	fmt.Println(id)
	t := rand.Intn(10)
	time.Sleep(time.Duration(t) * time.Second)
	fmt.Printf("I had slept %d seconds.\n", t)
	ch <- 1
}

func SomeGoRoutine() {
	ch := make(chan int)
	for i := 0; i < 3; i++ {
		go doSomething(ch, i)
	}
	<-ch
	fmt.Println("done")
}

/** output:
2
0
1
I had slept 1 seconds.
done
*/

In such a scenario, my http service provides an api, and n goroutines are generated in this api. When an error occurs in one of the goroutines, I want to end the entire request and return some error messages to the caller. If you don't use context, then we can easily think of using channel to achieve such a function, blocking in the main function, passing data into the channel in the goroutine, and ending the request when the channel receives the data. Context is also a similar principle, the management of goroutine is achieved through the transfer of channels between goroutine. The more interesting is the WithCancel method, which is different from our simple use of channels to pass data. WithCancel derives a child context, when the child context is about to end, it calls the cancel method recursively, and its child also calls the cancel method . Examples are as follows:

func ContextCancel() {
	ctx := context.Background()
	go func(ctx context.Context) {
		ctx1, cancel := context.WithCancel(ctx)
		go func(ctx1 context.Context) {
			ctx2, _ := context.WithCancel(ctx1)
			select {
			case <-ctx2.Done():
				fmt.Println("ctx2")
			}
		}(ctx1)
		cancel()
	}(ctx)
	time.Sleep(10 * time.Second)
}
/** ouput:
ctx2
*/

Welcome to pay attention to my public number: onepunchgo, leave me a message.

image

Published 20 original articles · praised 0 · visits 761

Guess you like

Origin blog.csdn.net/qq_31362439/article/details/105006977