Many people who use Go will encounter a context pack. Most of the time the context is used for downstream operations, such as sending Http requests, querying the database, or opening go-routines to perform asynchronous operations. The most common usage is passing data through it to downstream operations. Few people know, but a very useful context function is to cancel or stop the operation during execution. This article explains how we use the context cancellation feature, as well as some context-based usage and best practices to make your application faster and more robust. # # Why do we need to cancel the operation? Simply put, we need to cancel to avoid the system doing useless operations. Imagine a generic HTTP application where the user requests an HTTP server, and then the HTTP server queries the database and returns the data to the client:! [HTTP application] (https://raw.githubusercontent.com/studygolang/gctt-images/master/using-context-cancellation-in-go/1.png) If every step is perfect, time-consuming graphs will look like this:! [Time-consuming diagram] (https://raw.githubusercontent.com/studygolang/gctt-images/master/using-context-cancellation-in-go/2.png) However, What happens if the client interrupts the request halfway? Occurs, such as when the client closes the browser in the middle of the request. If the operation is not canceled, application Server and the database will continue their work, although the results of the work will be wasted. [Abnormal time-consuming diagram] (https://raw.githubusercontent.com/studygolang/gctt-images/master/using-context-cancellation-in-go/3.png) under ideal conditions , if we know the process (HTTP request in the example), we want the downstream operation to also stop:! [Ideal time-consuming diagram] (https://raw.githubusercontent.com/studygolang/gctt-images/master/using-context-cancellation-in-go/4.png) # # Go Cancel operation of context package now that we know why we need to cancel the operation, let's see how it's done in Golang. Because the "cancel operation" is highly dependent onBelow, or what has been done, it is very easy to implement through the context package. There are two steps you need to implement: 1. Listen for Cancel event 2. Trigger Cancel Event # # Listener Cancellation Event The _context_ package provides the _done () _ method, which returns a _channel_ that receives a _struct{}_ type when the context is charged the _ cancel _ event. To listen for a cancel event, simply wait for _<-CTX. Done () _ Good For example: an HTTP server takes 2 seconds to process a transaction, and if the request is canceled early, we want to return the result immediately: "' Gofunc main () {//Create an Http server this listens on port 8000http. Listenandserve (": 8000", http. Handlerfunc (Func (w http. Responsewriter, R *http. Request) {ctx: = R.context ()//This prints to STDOUT to show that processing have startedfmt. Fprint (OS. Stdout, "Processing request\n")///We use ' SELECT ' to execute a peice of code depending on which//channel receives a Messa GE Firstselect {case <-time. After (2 * time. Second)://If We receive a message after 2 seconds//that means the request have been processed//we then write this as the Responsew. Write ([]byte ("Request processed")) case <-ctx. Done ()://If The request gets cancelled, log it//to Stderrfmt.fprint (OS. Stderr, "Request Cancelled\n")})} "> Source code Address: https://github.com/sohamkamani/Blog-example-go-context-cancellation you can open [localhost:8000] (http://localhost:8000) with your browser by executing this code. If you close your browser within 2 seconds, you will see "Request canceled" printed on the console. # # Trigger Cancel event If you have an action that can be canceled, you can trigger a _ Cancel event through the context. You can use the _withcancel_ method provided by the context package, which returns a context object, and a method without parameters. This method will not return anything, just call when you want to cancel the context. The second case is dependency. Dependency means that when an operation fails, it causes other operations to fail. For example: We know in advance that an operation failed and we will cancel all dependent operations. "' Gofunc Operation1 (CTX context. Context) Error {//Let's assume that this operation failed for some reason//We use time. Sleep to simulate a resource intensive operationtime. Sleep (Time.millisecond) return errors. New ("Failed")}func Operation2 (CTX context. Context) {//We use a similar pattern to the HTTP server//that We saw in the earlier Exampleselect {case <-time. After (Time.millisecond): FMT. Println ("Done") case <-ctx. Done (): FMT. Println ("halted Operation2")}}func Main () {//Create a new contextctx: = Context. Background ()//Create A new context, with it cancellation function//from the original Contextctx, Cancel: = ContExt. Withcancel (CTX)//Run Operations:one in a different go Routinego func () {err: = Operation1 (CTX)//If this operation R Eturns an error//cancel all operations using this contextif err! = Nil {cancel ()}} ()//Run operation2 with the same conte XT We use for Operation1operation2 (CTX)} ' # # time-based cancellation the maximum processing time for a request by any program requires maintaining an SLA (Service level agreement), which can be done using time-based cancellation. This API is basically the same as the previous example, just a little bit more: "' go//the context would be cancelled after 3 seconds//If it needs to be cancelled earlier, the ' Cancel ' function can//is used, like Beforectx, cancel: = context. Withtimeout (CTX, 3*time. Second)//The context is cancelled on 2009-11-10 23:00:00ctx, Cancel: = context. Withdeadline (CTX, time. Date (Time, time). November, 0, 0, 0, time. UTC) "For example: HTTP API calls internal service. If the service is not responding for a long time, it is best to return the failure early and cancel the request. "' Gofunc Main () {//Create a new context//with a deadline of millisecondsctx: = context. Background () ctx, _ = context. Withtimeout (CTX, 100*time.millisecond)//Make a request, that would call the Google Homepagereq, _:= http. Newrequest (http. Methodget, "http://google.com", nil)//Associate The cancellable context we just created to the Requestreq = req. Withcontext (CTX)//Create a new HTTP client and execute the requestclient: = &http. Client{}res, Err: = client. Do (req)//If The request failed, log to stdoutif err! = Nil {fmt. Println ("Request failed:", err) return}//Print the statuscode if the Request succeedsfmt. Println ("Response received, status code:", Res.) StatusCode)} ' ' according to the speed of the Google page's response to your request, you will receive: ' Response received, status code:200 ' or ' request Failed:get/HTTP Google.com:context deadline exceeded "You can get the above 2 results by setting a timeout. # # Pitfalls and Considerations Although the Go context works well, it's a good idea to keep a few points in mind before using it. The most important thing is: the context can only be canceled once. If you want to propagate multiple errors, the context cancellation is not the best choice, the most usual scenario is that you really want to cancel an operation and notify the downstream operation that an error has occurred. Another way to remember is that a context instance runs through all of the methods and go-routines that you want to use to cancel the operation. To avoid using a canceled context as a parameter of _withtimeout_ or _WITHCANCEL_, this can lead to an indeterminate event.
via:https://www.sohamkamani.com/blog/golang/2018-06-17-golang-using-context-cancellation/
Author: Soham Kamani Translator: Nelsonken proofreading: polaris1119
This article by GCTT original compilation, go language Chinese network honor launches
This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove
202 Reads