首页 > 其他分享 >Golang上下文context

Golang上下文context

时间:2024-10-11 16:13:53浏览次数:1  
标签:fmt goroutine ctx Golang context time cancel 上下文

上篇内容我们主要讲解了net/http标准库的使用,其中包含如何创建POST请求、GET请求以及如何携带参数的请求。

Context介绍

context释义为上下文,在我们使用goroutine时一般使用context来进行元数据的传递,非元数据不建议使用context来进行传递。那么我们主要是用context用来做什么呢?其实我们主要是是用来在多个goroutine中传递取消信号,调用链路信息等。

使用建议

  1. 不要在结构体中存储context,将context类型作为函数的第一个参数,一般命名为ctx

  2. 不要向函数中传递nilcontext,如果不知道使用那个可以使用TODO进行占位使用都一样。

  3. 不要将函数所需的非元数据塞到context中。

  4. 同一个context可能会被传递到多个goroutine中,context对于多个goroutine是安全的。

context接口

type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}

context方法

我们可以看到context接口中有四个方法。

  • Deadline():返回值deadline表示当前context应该结束的时间,例如2sok表示是否有结束时间。

  • Done():返回一个只读的单向channel,当超时或者调用cancel(创建子context的一个返回函数)方法时,将会触发该方法。

  • Err():context被取消的原因。

  • Value():context共享数据存储。

创建根(父)context

  • context.Background():返回一个非nil的空context,没有任何值,不会被cancel,不会超时,没有截至日期。

  • context.TODO():返回一个非nil的 空context,没有任何值,不会被cancel,不会超时,没有截至日期。当不知道使用那个context时,用它。

图片

创建子context

  • WithValue:通过该函数可以在context中传递键值对,用于跨goroutine传递请求范围的值,但是要注意,这不是用于传递请求相关数据的首选方法,而是应该用于传递相关元数据。

    图片

  • WithCancle:通过该函数可以创建一个可取消的context并返回一个新的context和一个cancelFunc。当调用CancelFunc时,与该context相关联的所有goroutines都会收到取消信号.

    图片

  • WithTimeout:通过该函数可以创建一个带有超时时间的context。在指定的时间后过期,context会自动取消 。不要忘记defer cancel()

    图片

  • WithDeadline:通过该函数可以创建一个带有特定截至时间的context,在截至时间之后context会自动取消  不要忘记defer cancel()哦。

    图片

案例演示

WithValue

package main

import (
"context"
"fmt"
)

func main() {
parentContext := context.Background()
ctx1 := context.WithValue(parentContext, "key1", "value1")
ctx11 := context.WithValue(ctx1, "key11", "value11")
// 这里的儿子与孙子都是基于parentContext来说的哦
fmt.Println("儿子的money:", ctx1.Value("key1"))
fmt.Println("儿子将money给孙子了:", ctx11.Value("key1"))
fmt.Println("孙子个人money:", ctx11.Value("key11"))
fmt.Println("孙子想要儿子的money:", ctx1.Value("key11"))
}

运行结果为:

儿子的money: value1
儿子将money给孙子了: value1
孙子个人money: value11
孙子想要儿子的money: <nil>

说明:通过上边的案例我们应该可以看懂context中的value传递。

WithCancle

package main

import (
"context"
"fmt"
"time"
)

func main() {
// 这样写不要看不懂哦,只是将父context直接传入了
ctx, cancel := context.WithCancel(context.Background())
go fun1(ctx)
time.Sleep(6 * time.Second)
fmt.Println("使用cancel停止goroutine")
cancel()
time.Sleep(2 * time.Second)
fmt.Println("main")
}

func fun1(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("goroutine退出了哦", ctx.Err())
return
default:
fmt.Println("goroutine持续运行中")
time.Sleep(2 * time.Second)
}
}

}

运行结果为:

goroutine持续运行中
goroutine持续运行中
goroutine持续运行中
使用cancel停止goroutine
goroutine退出了哦 context canceled
main

说明:从上述运行结果我们可以看出,当调用cancelgoroutine停止了。并打印了退出的原因(ctx.Err())。

WithTimeout

package main

import (
"context"
"fmt"
"time"
)

func main() {
// 这样写不要看不懂哦,只是将父context直接传入了
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second)
go fun1(ctx)
time.Sleep(18 * time.Second)
defer cancel()
time.Sleep(2 * time.Second)
fmt.Println("main")
}

func fun1(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("goroutine退出了哦", ctx.Err())
return
default:
time.Sleep(2 * time.Second)
fmt.Println("goroutine持续运行中")

}
}

}

运行结果为:

goroutine持续运行中
goroutine持续运行中
goroutine持续运行中
goroutine退出了哦 context deadline exceeded
main

说明:通过上述代码的运行结果我们可以发现,当运行超过我们设置的时间(6*time.Second)时,会取消goroutine的运行,这也是我们打印的结果为什么时3goroutine持续运行中

WithDeadline

package main

import (
"context"
"fmt"
"time"
)

func main() {
// 这样写不要看不懂哦,只是将父context直接传入了
d := time.Now().Add(6 * time.Second)
ctx, cancel := context.WithDeadline(context.Background(), d)
go fun1(ctx)
defer cancel()
time.Sleep(10 * time.Second)
fmt.Println("main")
}

func fun1(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("goroutine退出了哦", ctx.Err())
return
default:
time.Sleep(2 * time.Second)
fmt.Println("goroutine持续运行中")

}
}

}

运行结果为:

goroutine持续运行中
goroutine持续运行中
goroutine持续运行中
goroutine退出了哦 context deadline exceeded
main

说明:根据打印结果我们可以发现,其实WithDeadlineWithTimeout差不多,只不过WithTimeout设置的是运行的时间,而WithDeadline表示goroutine运行到那个时间节点。

标签:fmt,goroutine,ctx,Golang,context,time,cancel,上下文
From: https://www.cnblogs.com/cheyunhua/p/18458645

相关文章

  • Golang模板template
    背景概述当我们在进行json字段选取以及渲染时,我们经常会见到{{}},其实这就是我们今天要讲解的模板即是template。例如prometheusAlert中的模板就是使用了改语法。必备技能字段选取❝{{.}}表示json的所有域,例如:{"name":"anruo","age":18},我们使用{{.}}就可以获取到所有......
  • [Java/Spring] 深入理解 : Spring ApplicationContext
    [Java/Spring]深入理解:SpringApplicationContext1概述:ApplicationContext简介2源码分析ApplicationContextpackageorg.springframework.context;publicinterfaceApplicationContextextendsEnvironmentCapable,ListableBeanFactory,HierarchicalBeanFactor......
  • [Java/Spring] 深入理解 : Spring BeanFactory / ApplicationContext、Environment、P
    PropertySource:解析环境资源及配置的底层组件org.springframework.core.env.PropertyResolverEnvironment:管理环境的配置与资源org.springframework.core.env.Environment其继承接口PropertyResolver属性解析器,用来解析不同属性源PropertySource里的key......
  • 28. 找出字符串中第一个匹配项的下标 Golang实现
    题目描述:给你两个字符串haystack和needle,请你在haystack字符串中找出needle字符串的第一个匹配项的下标(下标从0开始)。如果needle不是haystack的一部分,则返回-1。示例1:输入:haystack="sadbutsad",needle="sad"输出:0解释:"sad"在下标0和6处匹配。......
  • [编程笔记] 当前上下文中不存在名称"ViewBag"
    最近在弄另外一个项目,很长一段时间没接触MVC了,VisualStudio2022识别cshtml文件的时候,出了一点故障!很多ViewBag、@Html.Partial、@Html.FunctionBar()等这些地方都报波浪线了,提示不存在这个名称,但是代码是可以运行的,这种一般就是本地环境或者配置的问题了。......
  • Golang 中的强大 TUI 库 ——tview
    在命令行界面下创建丰富的用户交互界面是许多开发者的需求,而Golang语言中有一个非常出色的TUI(文本用户界面)库——tview。本文将详细介绍tview库,并与其他流行的TUI库进行对比,最后进行总结。一、tview库介绍tview是一个用于创建终端用户界面的Golang库。它提供......
  • IntelliJ IDEA(IDEA)下无法解析 ApplicationContext 中的方法 getBean
    只需要:删除过程目录下的.idea文件后,关闭IDEA,再重新打开IDEA即可解决“getBean”报红问题。(注意:前提是要保证有依赖(Spring核心库配置正确、依赖版本兼容)、配置正确(ApplicationContext 创建正确、有 Bean定义、扫描包正确)、编码问题(导入正确的类、方法调用正确))以上原理:.i......
  • linux 系统CPU 上下文切换(Context Switch)概念
    CPU上下文切换(ContextSwitch)是操作系统调度程序在不同任务之间切换CPU执行的过程。上下文切换的核心是保存当前任务的状态(也叫“上下文”),然后恢复下一个任务的状态,最终交给CPU执行。这种切换可能发生在进程、线程或者内核级别的不同上下文之间。上下文切换的详细过程保......
  • Golang反射解说
    在Go语言中,反射(Reflection)是一种强大的机制,允许程序在运行时检查、修改和操作变量的类型信息。反射主要用于处理那些在编译时无法确定类型的情况,比如处理接口类型的值、实现通用的函数等。Go语言中反射的基本概念和用法:基本概念1.反射类型(reflect.Type):表示Go语言中的任何类......
  • 函数的上下文
    函数的上下文概述在函数体的语句中,会出现this这个词,this就是函数的上下文函数中this是谁,就说明函数的上下文是谁函数中的this是谁,要看是如何调用的,因为this不是一成不变的比如我们看下面的例子varobj={ a:100, fun:function(){ console.log(this.a); }};我们......