golang context学习记录1
1.前言
一个请求,可能涉及多个API调用,多个goroutine,如何在多个API 之间,以及多个goroutine之间协作和传递信息,就是一个问题。
比如一个网络请求Request,需要开启一些goroutine去访问后端资源(比如,数据库,RPC服务等),这些goroutine又可能会开启其他的goroutine,如何跟踪和控制这些goroutine呢?
golang定义了 context包,用于解决这个问题。
context可以在多个API和进程之间,实现deadlines截止日期操作、cancelation signals取消操作以及传递request-scoped的值(即传递参数)。
context一个最大的特点是可以继承。父context,可以派生子context,子context有又可以派生子context。如果父context被取消,子context及其子context都会被取消。
常用派生的方法有:WithCancel WithDeadline WithTimeout WithValue.
其中,
WithCancel用于主动取消自身以及子context。WithDeadline和WithTimeout用于超时情况下的取消自身以及子context。WithTimeout实现上直接调用WithDeadline。WithValue用于context传递request-scoped的参数,而不是向函数传递的可选参数。
2.例子
下面例子演示如何控制多个goroutine的退出。
首先,启动3个goroutine,分别命名为"1"、"2"、"3",每个goroutine又启动一个goroutine。也就是有6个goroutine。它们之间的关系如下:
- 1
- 11
- 2
- 21
- 3
- 31
最后,在main中调用取消操作cancel,先是1,2,3收到信号退出,1,2,3退出的时候又调用它们的cancel,这样所有的goroutine都被取消并退出。
具体代码如下:
package main
import (
"context"
"fmt"
"time"
)
func PrintTask(ctx context.Context, taskName string) {
for {
select {
case <- ctx.Done():
fmt.Println("task:", taskName, " exit...")
return
default:
time.Sleep(1*time.Second)
fmt.Println("task:", taskName, " doing something...")
}
}
}
func mainTask(ctx context.Context, taskName string) {
ctx1, cancel := context.WithCancel(ctx)
defer cancel()
// create a new task
newTaskName := taskName + "1"
go PrintTask(ctx1, newTaskName)
for {
select {
case <- ctx.Done():
fmt.Println("task:", taskName, " exit...")
return
default:
time.Sleep(1*time.Second)
fmt.Println("task:", taskName, " doing something...")
}
}
}
func main() {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
go mainTask(ctx, "1")
go mainTask(ctx, "2")
go mainTask(ctx, "3")
time.Sleep(3*time.Second)
cancel()
fmt.Println("main exit...")
time.Sleep(3*time.Second)
}
输出
task: 1 doing something...
task: 21 doing something...
task: 11 doing something...
task: 3 doing something...
task: 2 doing something...
task: 31 doing something...
task: 3 doing something...
task: 2 doing something...
task: 11 doing something...
task: 21 doing something...
task: 31 doing something...
task: 1 doing something...
task: 11 doing something...
task: 3 doing something...
task: 1 doing something...
task: 21 doing something...
task: 2 doing something...
task: 31 doing something...
main exit...
task: 11 doing something...
task: 11 exit...
task: 21 doing something...
task: 21 exit...
task: 3 doing something...
task: 3 exit...
task: 31 doing something...
task: 31 exit...
task: 1 doing something...
task: 1 exit...
task: 2 doing something...
task: 2 exit...
更多参考
golang context学习记录1的更多相关文章
- golang context学习记录2
上篇文章中,我们已经学习了使用context实现控制多个goroutine的退出. 本文将继续介绍如何使用context实现超时情况下,让多个goroutine退出. 例子 首先,启动3个gorout ...
- golang "%p"学习记录随笔
对于获取slice的指针地址, 通过unsafe.Pointer 和 "%p"占位符两种方式得到的地址是不同的 s := make([]int, 1) t.Log(unsafe.P ...
- 【golang学习记录】环境搭建
[golang学习记录]环境搭建 一. 概述 本文是[golang学习记录]系列文章的第一篇,安装Go语言及搭建Go语言开发环境,接下来将详细记录自己学习 go 语言的过程,一方面是为了巩固自己学到的 ...
- Golang Context 的原理与实战
本文让我们一起来学习 golang Context 的使用和标准库中的Context的实现. golang context 包 一开始只是 Google 内部使用的一个 Golang 包,在 Gola ...
- Quartz 学习记录1
原因 公司有一些批量定时任务可能需要在夜间执行,用的是quartz和spring batch两个框架.quartz是个定时任务框架,spring batch是个批处理框架. 虽然我自己的小玩意儿平时不 ...
- Spring学习记录(九)---通过工厂方法配置bean
1. 使用静态工厂方法创建Bean,用到一个工厂类 例子:一个Car类,有brand和price属性. package com.guigu.spring.factory; public class C ...
- 【转】BLE 学习记录
原文网址:http://m.blog.csdn.net/blog/chiooo/43985401 BLE 学习记录 ANROID BLE 开发,基于 bluetoothlegatt 分析 mBluet ...
- 我的Spring学习记录(二)
本篇就简单的说一下Bean的装配和AOP 本篇的项目是在上一篇我的Spring学习记录(一) 中项目的基础上进行开发的 1. 使用setter方法和构造方法装配Bean 1.1 前期准备 使用sett ...
- 我的Spring学习记录(四)
虽然Spring管理这我们的Bean很方便,但是,我们需要使用xml配置大量的Bean信息,告诉Spring我们要干嘛,这还是挺烦的,毕竟当我们的Bean随之增多的话,xml的各种配置会让人很头疼. ...
随机推荐
- 利用python3 调用zabbix接口完成批量加聚合图形(screens)
在上一篇博客中,我们完成的利用python3 调用zabbix接口批量增加主机,增加主机的item,增加主机的图形! 接下来我们完成批量增加主机的screen 首先我们要增加screen需要哪些参数呢 ...
- 解决跨域问题,前端 live-server --port=1802 后端启动 localhost:1801,以及解决 vue 的 axios 请求整合
测试的源码文件内容点击跳转 前端引入 vue.js 与 axios.min.js <script src="https://cdn.bootcss.com/vue/2.6.10/vue ...
- oracle数据库连接问题org.springframework.jdbc.support.MetaDataAccessException: JDBC DatabaseMetaData method not implemented by JDBC driver - upgrade your driver...
org.springframework.jdbc.support.MetaDataAccessException: JDBC DatabaseMetaData method not implement ...
- 给Tomcat打开远程debug端口
>cd apache-tomcat-8.5.24 >cd conf >vim catalina.sh 在文件开始处添加: CATALINA_OPTS="-server -X ...
- MySQL面试题(二)
● 请你说一说mysql的四种隔离状态 参考回答: Mysql主要包含四种隔离状态: 事务隔离级别 脏读 不可重复读 幻读 读未提交(read-uncommitted) 是 是 是 不可重复读(rea ...
- 解决GitHub添加sshkey仍然无法访问clone远程仓库的问题
1 ssh -v git@github.com 通过这个命令打印调试信息 ebug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS rece ...
- requests:用于发送http请求,专为人类设计
介绍 requests模块是一个专门用来发送http请求的模块 如何发送请求 import requests """ 使用requests模块发送请求非常简单 首先请求有 ...
- Python——枚举(enum)
- 清北学堂提高组突破营游记day3
讲课人更换成dms. 真的今天快把我们逼疯了.. 今天主攻数据结构, 基本上看完我博客能理解个大概把, 1.LCA 安利之前个人博客链接.之前自己学过QWQ. 2.st表.同上. 3.字符串哈希.同上 ...
- qa角色记一次测试过程回溯
一.测试过程简述 a项目依赖b项目新功能,ab项目一起提测 1.测试人员:两老一新 2.测试过程:第一轮,三人执行用例 第二轮,三人各自模块发散 第三轮,三人交叉测试 第四轮,两老投入b项目性能以及接 ...