返回顶部
首页 > 资讯 > 后端开发 > GO >详解Golang中Context的三个常见应用场景
  • 876
分享到

详解Golang中Context的三个常见应用场景

Golang Context应用场景Golang Context应用Golang Context 2022-12-29 12:12:13 876人浏览 泡泡鱼
摘要

目录超时取消取消后续操作上下文传值超时取消 假设我们希望Http请求在给定时间内完成,超时自动取消。 首先定义超时上下文,设定时间返回取消函数(一旦超时用于清理资源)。调用取消函数取

超时取消

假设我们希望Http请求在给定时间内完成,超时自动取消。

首先定义超时上下文,设定时间返回取消函数(一旦超时用于清理资源)。调用取消函数取消后续操作,删除子上下文对父的引用。

    ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*80)
    defer cancel()
    req = req.WithContext(ctx)

还可以通过特定时间进行设定:

/ The context will be cancelled after 3 seconds
// If it needs to be cancelled earlier, the `cancel` function can
// be used, like before
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)

​​​​​​​// Setting a context deadline is similar to setting a timeout, except
// you specify a time when you want the context to cancel, rather than a duration.
// Here, the context will be cancelled on 2022-11-10 23:00:00
ctx, cancel := context.WithDeadline(ctx, time.Date(2022, time.November, 10, 23, 0, 0, 0, time.UTC))

完整实例如下:

func main() {
    //定义请求
	req, err := http.NewRequest(http.MethodGet, "https://www.baidu.com", nil)
	if err != nil {
		log.Fatal(err)
	}

    // 定义上下文
	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*80)
	defer cancel()
	req = req.WithContext(ctx)

    // 执行请求
	c := &http.Client{}
	res, err := c.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()

    // 输出日志
	out, err := io.ReadAll(res.Body)
	if err != nil {
		log.Fatal(err)
	}
	log.Println(string(out))
}

超时输出结果:

2022/12/27 14:36:00 Get "https://www.baidu.com": context deadline exceeded

我们可以调大超时时间,则能正常看到输出结果。

取消后续操作

有时请求被取消后,需要阻止系统继续做后续比必要的工作。请看下面用户发起的http请求,应用程序接收请求后查询数据库并返回查询结果:

正常流程如下:

但如果客户端取消了请求,如果没有取消,应用服务和数据库仍然继续工作,然后结果却不能反馈给客户端。理想状况为所有下游过程停止,如图所示:

考虑有两个相关操作的情况,“相关”的意思是如果一个失败了,另一个即使完成也没有意义了。如果已经知道前一个操作失败了,则希望取消所有相关的操作。请看示例:

func operation1(ctx context.Context) error {
	// 假设该操作因某种原因而失败
	// 下面模拟业务执行一定时间
	time.Sleep(100 * time.Millisecond)
	return errors.New("failed")
}

func operation2(ctx context.Context) {
	// 该方法要么正常执行完成
	// 要么取消,不再继续执行
	select {
	case <-time.After(500 * time.Millisecond):
		fmt.Println("done")
	case <-ctx.Done():
		fmt.Println("halted operation2")
	}
}

func main() {
	// 创建上下文
	ctx := context.Background()

	// 基于上下文创建需求上下文
	ctx, cancel := context.WithCancel(ctx)

	// 在不同协程中执行两个操作
	Go func() {
		err := operation1(ctx)
		// 如果该方法返回错误,则取消该上下文中的后续操作
		if err != nil {
			cancel()
		}
	}()

	// 实用相同上下文执行操作2
	operation2(ctx)
}

由于我们设置操作2执行时间较长,而操作1很快就报错,因此输出结果为操作2被取消:

halted operation2

上下文传值

我们可以实用上下文变量在不同协程中传递值。

假设一个操作需要调用函数多次,其中用于标识的公共ID需要被 日志记录,请看示例:

// 定义key,用于保存上下文值的键
const keyID = "id"

func main() {
    // 定义上下文值
	rand.Seed(time.Now().Unix())
	ctx := context.WithValue(context.Background(), keyID, rand.Int())
	operation1(ctx)
}

func operation1(ctx context.Context) {
	// do some work

	// we can get the value from the context by passing in the key
	log.Println("operation1 for id:", ctx.Value(keyID), " completed")
	operation2(ctx)
}

func operation2(ctx context.Context) {
	// do some work

	// this way, the same ID is passed from one function call to the next
	log.Println("operation2 for id:", ctx.Value(keyID), " completed")
}

这里在main函数中创建上下文,并采用键值对方式存储id值,从而后续函数调用时可以从上下文中获取该值。如图所示:

使用context变量在不同操作中传递信息非常有用,主要原因包括:

  • 线程安全: 一旦设置了上下文键,就不能修改它的值,可以使用context.WithValue方法可以设置新的值
  • 通用方法: 在Go的官方库和应用程序中大量使用上下文传递数据,我们当然最好也使用这种模式

到此这篇关于详解golang中Context的三个常见应用场景的文章就介绍到这了,更多相关Golang Context内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: 详解Golang中Context的三个常见应用场景

本文链接: https://lsjlt.com/news/176200.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 详解Golang中Context的三个常见应用场景
    目录超时取消取消后续操作上下文传值超时取消 假设我们希望HTTP请求在给定时间内完成,超时自动取消。 首先定义超时上下文,设定时间返回取消函数(一旦超时用于清理资源)。调用取消函数取...
    99+
    2022-12-29
    Golang Context应用场景 Golang Context应用 Golang Context
  • Golang中Context的常见应用场景有哪些
    这篇文章主要讲解了“Golang中Context的常见应用场景有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Golang中Context的常见应用场景有哪些”吧!超时取消假设我们希望H...
    99+
    2023-07-04
  • Golang上下文Context的常见应用场景
    目录Context类型emptyCtxcancelCtxcanceler接口timerCtxvalueCtx函数默认上下文Background()TODO()取消信号WithCanc...
    99+
    2023-05-16
    Golang Context应用场景 Golang Context上下文 Golang Context
  • Golang上下文Context的常见应用场景是什么
    这篇文章主要介绍了Golang上下文Context的常见应用场景是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Golang上下文Context的常见应用场景是什么文章都会有所收获,下面我们一起来看看吧。C...
    99+
    2023-07-06
  • Golang中context包使用场景和示例详解
    目录控制子协程退出超时控制上下文传递数据控制子协程退出 context包提供了一种机制,可以在多个goroutine之间进行通信和控制。使用Context包能够有效地控制程序的并发性...
    99+
    2023-05-19
    Golang context包使用场景 Golang context包使用 Golang context包 Golang context
  • 了解Redis常见应用场景
    目录一、String 场景二、Hash 场景三、List 场景四、Set 场景五、zSet 场景一、String 场景 计数功能: 例如掘金文章点击数量,阅读数量。 ...
    99+
    2024-04-02
  • 深入解析Redis中常见的应用场景
    前言 Redis是一个key-value存储系统,现在在各种系统中的使用越来越多,大部分情况下是因为其高性能的特性,被当做缓存使用,这里介绍下Redis经常遇到的使用场景。下面话不多说了,来一起看看详细的介...
    99+
    2022-06-04
    场景 常见 Redis
  • React中的Context应用场景分析
    Context定义和目的 Context 提供了一种在组件之间共享数据的方式,而不必显式地通过组件树的逐层传递 props。 应用场景 哪些数据会需要共享? Context 设计目...
    99+
    2024-04-02
  • Redis在PHP中的常见应用场景
    Redis是一种基于内存的键值存储数据库,它具有高性能、高可用性、高可扩展性等优点,被广泛应用于各个领域的数据存储和缓存优化。在PHP应用场景中,Redis也有着广泛的应用,本文主要介绍Redis在PHP中常见的应用场景。缓存优化缓存优化是...
    99+
    2023-05-15
    应用场景 PHP redis
  • Golang常见的应用场景在软件开发中有哪些?
    Golang作为一种开发语言,具有简洁高效、并发性能强等特点,因而在软件开发中有着广泛的应用场景。下面将介绍一些常见的应用场景。网络编程Golang在网络编程方面表现出色,特别适合构建高并发、高性能的服务器。它提供了丰富的网络库,开发人员可...
    99+
    2023-12-28
    云计算 web开发 分布式系统
  • 16个Redis的常见使用场景
     Redis 16 个常见使用场景 1、缓存 String类型 例如:热点数据缓存(例如报表、明星出轨),对象缓存、全页缓存、可以提升热点数据的访问数据。 2、数据共享分布...
    99+
    2024-04-02
  • vue中filter的应用场景详解
    filter一般用于过滤某些值,比如我这个字段是空,可是我想在前端显示“–”,就可以使用到它了。 最近碰到一个需求就是要给某些字段可以设置权限去以其他形式显示,比如以“***”显示...
    99+
    2024-04-02
  • 常见position布局的应用场景与技巧解析
    掌握常见position布局的使用场景与技巧,需要具体代码示例引言:在前端开发中,布局是至关重要的一环。而position布局在实现网页页面布局中起到了重要的作用。它可以帮助我们实现精确的页面元素定位和交互效果的实现。本文将介绍常见的pos...
    99+
    2023-12-26
    float (浮动) Flexbox (弹性盒子) Grid (网格布局)
  • 数组在Java中有哪些常见的应用场景?
    Java是一门广泛应用的编程语言,它有着丰富的数据结构,其中数组是最基础也是最常用的数据结构之一。数组是一种容器,它能够存储多个相同类型的元素,这些元素在内存中是连续存储的。本文将介绍在Java中数组的常见应用场景以及相关的代码实现。 1....
    99+
    2023-07-20
    unix 自然语言处理 数组
  • js中symbol类型以及symbol的三大应用场景详解
    目录1.什么是symbol2.注意点3. symbol的应用4.symbol自带的方法总结1.什么是symbol 1.什么Symbol Symbol是ES6中新增的一种数据类型, 被...
    99+
    2024-04-02
  • 云主机的常见应用场景有哪些
    云主机的应用场景有:1.企业官网;2.高并发应用或网站;3.高I/O要求数据库;4.访问量波动剧烈的网站;具体分析如下:企业官网网站初始阶段访问量小,可以选择配置的云主机,随着网站发展,可以随时升级云主机配置,或者增加云主机实例数量,无需担...
    99+
    2024-04-02
  • Go语言常见的应用场景有哪些?
    go语言适用于多种场景,包括后端开发、微服务架构、云计算、大数据处理、机器学习,以及构建restful api。其中,使用go构建restful api的简单步骤包括:设置路由器、定义处...
    99+
    2024-04-03
    应用场景 go语言
  • 在H5开发中常见的position属性的应用场景
    H5开发中position属性的常见应用场景,需要具体代码示例在H5开发中,CSS的position属性非常重要,它控制元素在网页中的定位方式。通过合理应用position属性,我们可以实现页面布局的灵活性和美观性。在本文中,我们将介绍po...
    99+
    2023-12-27
    应用场景 常见 position
  • Python中使用len函数的用法和常见应用场景
    Python中len函数的用法和应用场景 在Python中,len函数是用于获取对象的长度或项数的内置函数。len函数主要用于字符串、列表、元组、字典和集合等数据类型,通过返回一个整数来表示对象的长度或者项数。在本文中,我们将详...
    99+
    2024-01-13
  • Vue常见组件间通信方案及典型应用场景详解
    目录什么是组件通信1、父子组件通信场景2、兄弟组件通信场景3、根组件和后代组件通信场景4、插槽通信场景5 无直接关系的组件通信场景6 大型项目中的复杂组件通信场景 - Vuex状态管...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作