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的各种配置会让人很头疼. ...
随机推荐
- 【转载】java工程师学习之路---给自己的目标
想学习或者提升java的可以看看,单从java角度来看总结的虽然还是很全面的,主要是为了自己看 http://blog.csdn.net/peace1213/article/details/50849 ...
- hive元数据库理解
在hive2.1.1 里面一共有59张表 表1 VERSION ; version表存hive的版本信息,该表中数据只有一条,如果存在多条,会造成hive启动不起来. 表2 DBS select * ...
- 利用python3 爬虫 定制版妹子图mzitu爬取
在刚开始学爬虫的时候,用来练手的基础爬虫就是爬取各种妹子图片,前几天同时说了这个,便准备随便写一个...最后发现真是三天不练..什么都记不住了!!所以花了政治一天重新写了一个爬虫程序,并且支持按照时间 ...
- Delphi 参数的传递
- Zabbix报错:"Zabbix http poller processes more than 75% busy"的解决
一.钉钉收到告警 主机名称:Zabbix服务端-172.28.18.75 IP地址 :127.0.0.1 告警时间:2019.10.22 13:34:39 告警信息:Zabbix http polle ...
- Java语言基础(5)
1 if-else语句(二) 案例:Demo1~Demo4 import java.util.Scanner; public class Demo1 { //在main方法中,从控制台输入任意的一个整 ...
- Java 和JavaScript实现C#中的String.format效果
1.Java实现 /** * 需要引入com.alibaba.fastjson.1.2.8 * String result2=HuaatUtil.format(templa ...
- Gym - 102040B Counting Inversion (数位dp)
题意:求[a,b]区间内的数字中正序对的个数. 具体思路参考: https://blog.csdn.net/weixin_43135318/article/details/88061396 https ...
- python之ORM
pymysql python操作数据库的基本步骤: 导入相应的python模块: 使用connect函数连接数据库,并返回一个connection对象: 通过connection对象的cursor方法 ...
- Python 文件I/O Ⅳ
Python里的目录: 所有文件都包含在各个不同的目录下,不过Python也能轻松处理.os模块http://www.xuanhe.net/有许多方法能帮你创建,删除和更改目录. mkdir()方法 ...