context
package
The context
package defines the Context
type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.
This package introduces the Context
type, which can carry variables related to a specific request, expiration times, or signals for indicating the completion of execution.
By associating values with the Context
type, it is easy to express whether a specific call has a successful authentication.
official doc (opens in a new tab)
The following example demonstrates how to add a variable to the Context
variable that stores information about the logged-in user:
package main
import (
"context"
"fmt"
)
func main() {
type ContextKey string
user := struct {
Name string
}{
Name: "John",
}
userContextKey := ContextKey("User")
ctx := context.WithValue(context.Background(), userContextKey, user)
if v := ctx.Value(userContextKey); v != nil {
fmt.Println("Found value:", v)
return
}
}
You can run the code snippet above here (opens in a new tab).
A Context
variable can be created along with a cancel
function, which can be used to signal the termination of a request:
package main
import (
"context"
"fmt"
"time"
)
func main() {
// The cancel function will cancel the context
ctx, cancel := context.WithCancel(context.Background())
go func() {
fmt.Println("Waiting for context cancellation in the goroutine...")
<-ctx.Done() // The function continues as soon as the context is cancelled
}()
time.Sleep(time.Second) // The main goroutine sleeps for a second
fmt.Println("Cancelling the context")
cancel() // Cancels the context
}
You can run the code snippet above here (opens in a new tab).
The Context
type can also be used to define deadlines, signaling the termination of a call:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx := context.Background()
deadline := time.Now().Add(time.Second * 1)
ctx, cancel := context.WithDeadline(ctx, deadline)
// The ctx will be expired, but it is a good practice to call its
// cancellation function in any case to avoid keeping its parent alive longer than necessary.
defer cancel()
fmt.Println("Waiting for the deadline")
// Blocks until it receives a value
// from the context's channel
<-ctx.Done()
fmt.Println(ctx.Err())
}
You can run the code snippet above here (opens in a new tab).
A Context
variable can also be created with a predefined timeout value, which signals the termination of a call. The difference from the previous example is that you specify a time interval rather than a specific time:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, time.Second*1) // Sets the timeout to 1 second
defer cancel()
select {
case <-time.After(10 * time.Second):
fmt.Println("Overslept")
case <-ctx.Done():
fmt.Println(ctx.Err()) // Prints "context deadline exceeded"
}
}
You can run the code snippet above here (opens in a new tab).