我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Golang中context包使用场景和示例详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Golang中context包使用场景和示例详解

控制子协程退出

context包提供了一种机制,可以在多个goroutine之间进行通信和控制。使用Context包能够有效地控制程序的并发性,提高程序的健壮性和性能。

Golang是没有办法让其他goroutine退出的,goroutine只能自己退出。之所以说context包可以控制子协程退出意思是子协程可以接收到主协程发出的退出信号,然后自己退出。看如下示例代码:

package main

import (
	"context"
	"errors"
	"sync"
)

func request(ctx context.Context, url string) error {
	result := make(chan int)
	err := make(chan error)
	go func() {
		// 假如isSuccess是请求返回的结果,成功则通过result传递成功信息,错误通过error传递错误信息
		isSuccess := true
		if isSuccess {
			result <- 1
		} else {
			err <- errors.New("some error happen")
		}
	}()

	select {
	case <-ctx.Done():
		// 其他请求失败
		return ctx.Err()
	case e := <-err:
		// 本次请求失败,返回错误信息
		return e
	case <-result:
		// 本此请求成功,不返回错误信息
		return nil
	}
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	// 调用接口a
	err := request(ctx, "https://xxx.com/a")
	if err != nil {
		return
	}
	wg := sync.WaitGroup{}
	// 调用接口b
	wg.Add(1)
	go func() {
		defer wg.Done()
		err := request(ctx, "https://xxx.com/b")
		if err != nil {
			cancel()
		}
	}()
	// 调用接口c
	wg.Add(1)
	go func() {
		defer wg.Done()
		err := request(ctx, "https://xxx.com/c")
		if err != nil {
			cancel()
		}
	}()
	wg.Wait()
}

首先调用context.WithCancel方法构造了一个Context和返回了一个cancel函数,其他goroutine调用的方法都传入了这个Context作为第一个参数,当主goroutine想要告诉所有goroutine需要退出的时候,通过调用cancel函数把退出的信息告诉所有的goroutine。所有goroutine通过监听ctx.Done返回的channel得到退出信号然后退出。

超时控制

例如查询数据库、调用RPC服务、调用HTTP接口等场景,这些操作都是阻塞的,如果一直不返回数据的话,会影响产品的用户体验。针对这些情况的解决方式通常是设置一个超时间,超过后自动取消操作。

使用context包中的WithDeadline和WithTimeout方法可以实现这个解决方法。先看如下例子:

package main

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

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
    defer cancel()

    select {
    case <-time.After(1 * time.Second):
        fmt.Println("overslept")
    case <-ctx.Done():
        fmt.Println(ctx.Err()) // 输出 "context deadline exceeded"
    }
}

因为设置的超时时间是50毫秒,所以select会进入第二个case,会输出“context deadline exceeded”。

Golang的net/http包发起http请求的时候是实现了超时控制的,看如下代码:

package main

import (
	"context"
	"io"
	"log"
	"net/http"
	"time"
)

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

	// 构造一个超时间为50毫秒的Context
	ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
	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))
}

执行后会输出“context deadline exceeded”,如果将context.WithTimeout方法的timeout参数调大一些,就可以看到正常的返回数据。

上下文传递数据

这个作用在链路追踪中非常重要,链路追踪需要将traceID层层往下传递,在服务间传递。

type traceIdKey struct{}{}

// 定义固定的Key
var TraceIdKey = traceIdKey{}

func ServeHTTP(w http.ResponseWriter, req *http.Request){
  // 首先从请求中获取到traceID
  traceId := getTraceIdFromRequest(req)
  // 将Key存入Context中
  ctx := context.WithValue(req.Context(), TraceIdKey, traceId)
  // 设置超时时间
  ctx = context.WithTimeout(ctx, time.Second)
  // 携带traceId发起rpc请求
  repResp := RequestRPC(ctx, ...)
  // 携带traceId查询DB
  dbResp := RequestDB(ctx, ...)
  // ...
}

func RequestRPC(ctx context.Context, ...) interface{} {
    // 获取traceid,在调用rpc时记录日志
    traceId, _ := ctx.Value(TraceIdKey)
    // 发起请求

    // ...
    return
}

接收到请求后,通过req获取到traceId并记录到Context中,在调用其他RPC服务和查询DB时,传入构造的Context。在后续代码中,可以通过Context拿到存入的traceId。

以上就是Golang中context包使用场景和示例详解的详细内容,更多关于Golang context包使用的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Golang中context包使用场景和示例详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Golang中context包使用场景和示例详解

这篇文章结合示例代码介绍了context包的几种使用场景,文中有详细的代码示例,对学习或工作有一定的帮助,需要的朋友可以参考下
2023-05-19

Golang中context包使用场景和示例详解

Golangcontext包使用场景Golangcontext包提供了一种机制,可以在goroutine之间传递上下文信息,包括取消信号、截止日期和值。它可用于处理各种场景,例如:取消操作设置截止日期传递值具体示例:取消操作:import"context"ctx,cancel:=context.WithCancel(context.Background())//取消上下文cancel()设置截止日期:import"context"ctx,cancel:=context.WithTimeout(contex
Golang中context包使用场景和示例详解
2024-04-23

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

Golang context主要用于定义超时取消,取消后续操作,在不同操作中传递值。本文通过简单易懂的示例进行说明,感兴趣的可以了解一下
2022-12-29

JS前端中的设计模式和使用场景示例详解

这篇文章主要为大家介绍了JS前端中的设计模式和使用场景示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

详解Golang中Context的原理和使用技巧

GoContext原理和使用技巧GoContext用于传递请求级数据,提供上下文信息(如请求ID、超时、终止请求通道和值存储)。Context按照树形结构组织,父Context创建子Context并继承数据。Context可用于请求取消、超时和值存储。最佳实践包括创建特定于请求的Context、使用Context值存储、避免直接使用context.Background()以及使用context.Context接口。示例演示了如何使用Context进行请求取消,当请求在超时前被取消时,会输出“Request
详解Golang中Context的原理和使用技巧
2024-04-23

Kotlin协程Context应用使用示例详解

这篇文章主要为大家介绍了Kotlin协程Context应用使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-08

golang函数闭包实现的原理和使用场景

go 中闭包原理:函数内嵌函数返回时,内嵌函数可访问外层函数变量,形成封闭环境。使用场景:1. 保持状态:闭包可维护内嵌函数状态,即使外层函数已返回;2. 延迟执行:用于延迟执行代码;3. 创建回调函数:通过事件触发调用;4. 模拟对象:用
golang函数闭包实现的原理和使用场景
2024-04-23

函数指针和闭包在Golang中的应用场景

函数指针在 go 中用于函数回调、延迟执行和多态性。闭包用于状态管理、事件处理和延迟初始化。函数指针和闭包在 Go 中的应用场景函数指针函数指针是指向函数的变量。可以使用 func 关键字声明函数指针类型:type Fn func(in
函数指针和闭包在Golang中的应用场景
2024-04-15

go-cache的基本使用场景示例解析

这篇文章主要为大家介绍了go-cache的基本使用场景示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-17

解析Golang中接口的使用场景和注意事项

Golang中接口的使用场景和注意事项解析Golang作为一门静态类型语言,引入了接口(interface)的概念,以便更好地支持面向对象的编程方式。接口在Golang中是一个非常重要的概念,在实际开发中经常用到。本文将从使用场景和注意事
解析Golang中接口的使用场景和注意事项
2024-01-24

vue3自定义插件的作用场景及使用示例详解

这篇文章主要为大家介绍了vue3自定义插件的作用场景及使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-23

ChatGPT使用案例过程场景详细讲解

这篇文章主要为大家介绍了ChatGPT使用案例过程场景的详细讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-17

详解Java中$符的各种使用场景

在Java编程中,我们会经常看到$符的身影,比如经常在配置文件中看到$符号作为变量占位符,用于在运行时动态地获取变量值。本文将详细介绍$符号在Java编程中的各种应用场景,以帮助您更好地理解和运用这个符号,感兴趣的小伙伴可以收藏一下
2023-05-17

mysql主从同步原理及应用场景示例详解

这篇文章主要为大家介绍了mysql主从同步原理及应用场景示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

Golang中协程和线程的异同及使用场景

Golang中协程和线程的区别与应用场景在Golang中,协程(goroutine)和线程(thread)是两种并发编程的方式。它们在原理和应用场景上有着明显的差异。本文将分别介绍协程和线程,并通过具体的代码示例说明它们的区别和应用场景。
Golang中协程和线程的异同及使用场景
2024-01-24

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录