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的各种配置会让人很头疼. ...
随机推荐
- 利用druid sql parser搞一些事情
在最近的项目开发中,有这样一个需求,就是给定一个查询的sql,在where语句中添加几个条件语句.刚开始想的是,是否能用正则去做这个事情呢?其实不用语法树还是有一点困难的. 经过一系列google,看 ...
- Linux下安装配置启动RabbitMQ
Linux版本:Centos 7RabbitMQ依赖erlang所以需要先安装erlang以及他需要的环境 安装erlang http://www.erlang.org/downloads 拿最新的版 ...
- Gh0st与云安全
黑产攻击途径升级,云服务成重灾区 在我们的印象里,黑产以及相关的肉鸡DDOS攻击总是离我们很远.可实际情况并非如此,特别是在云服务大行其道的今天. 日前,腾讯反病毒实验室就观察到了国内云服务中Gh0s ...
- kernel module insmod错误
kernel模块配置 Enable loadable module support 打开可加载模块支持,如果打开它则必须通过"make modules_install"把内核模块安 ...
- 00常见的Linux系统版本
linux系统内核与linux发行套件系统并不相同: linux系统内核指的是一个由Linus Torvalds负责维护,提供硬件抽象层.硬盘及文件系统控制及多任务功能的系统核心程序. linux发行 ...
- 【洛谷P3957】跳房子
题目大意:给定一个数轴和 N 个点,点有点权,现从 0 位置出发,初始时每次只能走 d 的距离,可以在数轴上任意位置停下,此时,会得到一个点权和.现允许支付 x 的费用,使得每次可以走的距离为一个范围 ...
- 关于jq中input的value值clone的问题
如果想将input进行克隆,然后在后面显示出来并修改input里面的文字,这时就会发现一个问题,就是你克隆出来的value值始终是你克隆时的value,检查页面元素你就会发现,这时需要对克隆之后的in ...
- LOJ-6284-数列分块入门8
链接: https://loj.ac/problem/6284 题意: 给出一个长为 的数列,以及 个操作,操作涉及区间询问等于一个数 的元素,并将这个区间的所有元素改为 . 思路: 维护一个分块是否 ...
- 15.DRF学习以及相关源码阅读
1.http请求协议 代码很枯燥,结果和奇妙. 1.cbv django.vuews import View classs LoginView(View): def get(self,requset) ...
- Spring配置文件beans标签报错问题解决
因为有很多配置是复制过来的,附带的很多注释的格式会导致报错,所以可以要试试把注释去掉,只有配置文件的话可能就不会报错了.