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标签报错问题解决
			因为有很多配置是复制过来的,附带的很多注释的格式会导致报错,所以可以要试试把注释去掉,只有配置文件的话可能就不会报错了. 
