Go语言Context (ctx)的基础概念与用法

这篇具有很好参考价值的文章主要介绍了Go语言Context (ctx)的基础概念与用法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

ctx字面意思上下文,是golang中特有的一种语法,几乎每一个程序中都会通篇传递着一个ctx。而一些框架又对其进行二次封装,诸如Gin框架中的c *gin.Context。因此此次进行ctx的学习并记录。

设计原理

这是ctx的接口部分,其提供了一个接口及许多函数、结构体(如图)。

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

Go语言Context (ctx)的基础概念与用法,Golang,golang,开发语言

其通过context.Background、context.TODO、context.WithDeadline 和 context.WithValue来返回实现这个接口的结构体。

goroutine树和ctx是上下传递的,会从顶层一步步传往底层。详见

Go语言Context (ctx)的基础概念与用法,Golang,golang,开发语言

常见用法

控制goroutine

多个goroutine运行,如何控制其结束?
最Low的办法自然是造一个bool全局变量,多个goroutine中检测其bool值,若改变,则停止。
但这样显然是不合理的,于是便可以通过select+chan来进行控制,即在goroutine中放一个select,其中通过chan到某个值,就停止。

func main() {
	stop := make(chan bool)

	go func() {
		for {
			select {
			case <-stop:    // 收到了停滞信号
				fmt.Println("监控退出,停止了...")
				return
			default:
				fmt.Println("goroutine监控中...")
				time.Sleep(2 * time.Second)
			}
		}
	}()

	time.Sleep(10 * time.Second)
	fmt.Println("可以了,通知监控停止")
	stop<- true

	//为了检测监控过是否停止,如果没有监控输出,就表示停止了
	time.Sleep(5 * time.Second)
}

但这样也有很大的局限性,比如我的goroutine中又新建了goroutine,这种无法在程序开始前写到的地方,该如何接收?
因此便可以用到ctx来进行控制。

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	go func(ctx context.Context) {
		for {
			select {
			case <-ctx.Done():
				fmt.Println("监控退出,停止了...")
				return
			default:
				fmt.Println("goroutine监控中...")
				time.Sleep(2 * time.Second)
			}
		}
	}(ctx)

	time.Sleep(10 * time.Second)
	fmt.Println("可以了,通知监控停止")
	cancel()
	//为了检测监控过是否停止,如果没有监控输出,就表示停止了
	time.Sleep(5 * time.Second)
}

两个方法看似一样,只是将手动向<-stop收发,换成了使用cancel()<-ctx.Done()。根据源码可以看出,其底层原理也是通过chan在进行通信,但是由于ctxgoroutine树,所以可以解决goroutine中新建goroutine的问题,从而更优雅的关闭goroutine。

传递元数据

通过ctx.Value("key")来读取,通过ctx = context.WithValue(ctx, "key", value)来设置。

但仅建议传递内置类型的数据。不建议传递重要数据,比如传递 签名、trace_id这类值。

超时控制

即通过context.WithDeadline(ctx, time.Now().Add(10*time.Second))设置这个ctx的关闭时间。

通过设置deadline,可以防止一个请求超时导致服务器问题。

需要注意的是不同ctx中deadline不一致导致问题。
(一次我使用context.Context*gin.Context时遇到了莫名其妙的超时,就是因为这个不一致)

使用注意事项

1、不要把 Context 放在结构体中,要以参数的方式传递。
2、以 Context 作为参数的函数方法,应该把 Context 作为第一个参数,放在第一位。
3、给一个函数方法传递 Context 的时候,不要传递 nil,如果不知道传递什么,就使用 context.TODO。
4、Context 的 Value 相关方法应该传递必须的数据,不要什么数据都使用这个传递。
5、Context 是线程安全的,可以放心的在多个 goroutine 中传递。

参考文献

6.1 上下文 Context #

深度解密Go语言之context

一文吃透 Go 语言解密之上下文 Context

【Go语言】小白也能看懂的context包详解:从入门到精通

Golang 中 context 的使用方式文章来源地址https://www.toymoban.com/news/detail-813993.html

到了这里,关于Go语言Context (ctx)的基础概念与用法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 100天精通Golang(基础入门篇)——第15天:深入解析Go语言中函数的应用:从基础到进阶,助您精通函数编程!(进阶)

    🌷 博主 libin9iOak带您 Go to Golang Language.✨ 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批

    2024年02月12日
    浏览(66)
  • Golang:Go语言结构

    在我们开始学习 Go 编程语言的基础构建模块前,让我们先来了解 Go 语言最简单程序的结构。 Go 语言的基础组成有以下几个部分: 包声明 引入包 函数 变量 语句 表达式 注释 接下来让我们来看下简单的代码,该代码输出了\\\"Hello World!\\\": 让我们来看下以上程序的各个部分: 第一

    2024年02月10日
    浏览(57)
  • 【Golang】Golang进阶系列教程--Go 语言数组和切片的区别

    在 Go 语言中,数组和切片看起来很像,但其实它们又有很多的不同之处,这篇文章就来说说它们到底有哪些不同。 数组和切片是两个常用的数据结构。它们都可以用于存储一组相同类型的元素,但在底层实现和使用方式上存在一些重要的区别。 Go 中数组的长度是不可改变的

    2024年02月15日
    浏览(56)
  • 【Golang】Golang进阶系列教程--Go 语言切片是如何扩容的?

    在 Go 语言中,有一个很常用的数据结构,那就是切片(Slice)。 切片是一个拥有相同类型元素的可变长度的序列,它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。 切片是一种引用类型,它有三个属性:指针,长度和容量。 底层源码定义如下: 指针: 指向

    2024年02月14日
    浏览(62)
  • 【Golang】Golang进阶系列教程--Go 语言 map 如何顺序读取?

    Go 语言中的 map 是一种非常强大的数据结构,它允许我们快速地存储和检索键值对。 然而,当我们遍历 map 时,会有一个有趣的现象,那就是输出的键值对顺序是不确定的。 先看一段代码示例: 当我们多执行几次这段代码时,就会发现,输出的顺序是不同的。 首先,Go 语言

    2024年02月14日
    浏览(65)
  • Go语言中sync.Map、sync.Pool和Context的用法

    目录 【sync.Map】 实现线程安全的 map 类型  使用 sync.Map 实现并发读写的map 【sync.Pool】 使用 带缓冲channel 实现对象池 使用 sync.Pool 创建临时对象池 【Context 上下文】 Context应用:实现带超时功能的远程调用 Context应用:监控指令  Context应用:取消关联任务 之前在 Go语言中ar

    2024年02月05日
    浏览(43)
  • 【GoLang】MAC安装Go语言环境

    小试牛刀 首先安装VScode软件 或者pycharm mac安装brew软件  brew install go 报了一个错误 不提供这个支持  重新brew install go 之后又重新brew reinstall go 使用go version 可以看到go 的版本 使用go env  可以看到go安装后的配置 配置一个环境变量 vim ~/.zshrc,  

    2024年02月15日
    浏览(56)
  • 【Golang】VScode配置Go语言环境

    安装VScode请参考我的上一篇博客:VScode安装_㫪548的博客-CSDN博客 接下来我们直接进入正题: Go语言(又称Golang)是一种开源的编程语言,由Google开发并于2009年首次发布。Go语言具有简洁、高效、可靠和易于阅读的特点,被设计用于解决大型项目的开发需求。它结合了静态类型

    2024年02月03日
    浏览(63)
  • Go语言(Golang)数据库编程

    要想连接到 SQL 数据库,首先需要加载目标数据库的驱动,驱动里面包含着于该数据库交互的逻辑。 sql.Open() 数据库驱动的名称 数据源名称 得到一个指向 sql.DB 这个 struct 的指针 sql.DB 是用来操作数据库的,它代表了0个或者多个底层连接的池,这些连接由sql 包来维护,sql 包会

    2024年02月03日
    浏览(86)
  • 【Golang】Golang进阶系列教程--为什么 Go 语言 struct 要使用 tags

    在 Go 语言中,struct 是一种常见的数据类型,它可以用来表示复杂的数据结构。在 struct 中,我们可以定义多个字段,每个字段可以有不同的类型和名称。 除了这些基本信息之外,Go 还提供了 struct tags,它可以用来指定 struct 中每个字段的元信息。 在本文中,我们将探讨为什

    2024年02月15日
    浏览(74)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包