golang 之 context包

概述

    context是Go中广泛使用的程序包,由Google官方开发,在1.7版本引入。它用来简化在多个go routine传递上下文数据、(手动/超时)中止routine树等操作,比如,官方http包使用context传递请求的上下文数据,gRpc使用context来终止某个请求产生的routine树。每个Context应该视为只读的,通过WithCancel、WithDeadline、WithTimeout和WithValue函数可以基于现有的一个Context(称为父Context)派生出一个新的Context(称为子Context)。其中WithCancel、WithDeadline和WithTimeout函数除了返回一个派生的Context以外,还会返回一个与之关联CancelFunc类型的函数,用于关闭Context。通过调用CancelFunc来关闭关联的Context时,基于该Context所派生的Context也都会被关闭,并且会将自己从父Context中移除,停止和它相关的timer。

核心接口

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key interface{}) interface{}
}

 根据如上接口显示对每个方法介绍

  • Done会返回一个channel,当该context被取消的时候,该channel会被关闭,同时对应的使用该context的routine也应该结束并返回。
  • Context中的方法是协程安全的,这也就代表了在父routine中创建的context,可以传递给任意数量的routine并让他们同时访问。
  • Deadline会返回一个超时时间,routine获得了超时时间后,可以对某些io操作设定超时时间。
  • Value可以让routine共享一些数据,当然获得数据是协程安全的。

在请求处理的过程中,会调用各层的函数,每层的函数会创建自己的routine,是一个routine树。所以,context也应该反映并实现成一棵树。

创建context

在创建context时会通过context.Background函数的返回值是一个空的context,作为树的根结点。并且提供4个常用函数去创建其子节点。

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithValue(parent Context, key interface{}, val interface{}) Context

 需要注意的是每个函数都会返回一个CancelFunc。调用CancelFunc对象将撤销对应的Context对象,这样父结点的所在的环境中,获得了撤销子节点context的权利,当触发某些条件时,可以调用CancelFunc对象来终止子结点树的所有routine。

我们在子集中可以通过 cxt.Done()是否为空来判断。

select {
    case <-cxt.Done():
        // do some cleaning and return
}

WithDeadlineWithTimeoutWithCancel多了一个时间参数,它指示context存活的最长时间。如果超过了过期时间,会自动撤销它的子context。所以context的生命期是由父context的routine和deadline共同决定的。

WithValue返回parent的一个副本,该副本保存了传入的key/value,而调用Context接口的Value(key)方法就可以得到val。注意在同一个context中设置key/value,若key相同,值会被覆盖。

示例

package main

import (
	"fmt"
	"time"
	"golang.org/x/net/context"
)

func main() {
	ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*5)
	ctx = context.WithValue(ctx, "Test", "123456")
	defer cancelFunc()

	if t, ok := ctx.Deadline(); ok {
		fmt.Println(time.Now())
		fmt.Println(t.String())
	}
	go func(ctx context.Context) {
		fmt.Println(ctx.Value("Test"))
		for {
			select {
			case <-ctx.Done():
				fmt.Println(ctx.Err())
				return
		   	default:
		   		continue
			}
		}
	}(ctx)
	time.Sleep(time.Second * 3)
}

 


原文地址:https://www.cnblogs.com/flash55/p/11160705.html

时间: 2024-11-15 00:24:51

golang 之 context包的相关文章

golang中context包学习

摘要 go语言中goroutine之间的关联关系,缺乏维护,在erlang中有专门的机制来保障新开仟程的生命周期, 在go语言中,只能通过channel + select来实现,但不够直观,感觉很绕. Context 通常被译作 上下文 ,它是一个比较抽象的概念.在公司技术讨论时也经常会提到 上下文 .一般理解为程序单元的一个运行状态.现场.快照,而翻译中 上下 又很好地诠释了其本质,上下上下则是存在上下层的传递, 上 会把内容传递给 下 .在Go语言中,程序单元也就指的是Goroutine.

Golang Context 包详解

Golang Context 包详解 0. 引言 在 Go 语言编写的服务器程序中,服务器通常要为每个 HTTP 请求创建一个 goroutine 以并发地处理业务.同时,这个 goroutine 也可能会创建更多的 goroutine 来访问数据库或者 RPC 服务. 当这个请求超时或者被终止的时候,需要优雅地退出所有衍生的 goroutine,并释放资源.因此,我们需要一种机制来通知衍生 goroutine 请求已被取消. 比如以下例子,sleepRandom_1 的结束就无法通知到 sle

golang的sync包例子

package main import ( "fmt" "sync" ) var wg sync.WaitGroup func asyncTestFunc() { for i := 0; i < 100; i++ { fmt.Println(i) } wg.Done() } func main() { wg.Add(1) go asyncTestFunc() wg.Wait() } golang的sync包例子

golang的io包

package io import "io" io包提供了对I/O原语的基本接口.本包的基本任务是包装这些原语已有的实现(如os包里的原语),使之成为共享的公共接口,这些公共接口抽象出了泛用的函数并附加了一些相关的原语的操作. 因为这些接口和原语是对底层实现完全不同的低水平操作的包装,除非得到其它方面的通知,客户端不应假设它们是并发执行安全的. Index Variables type Reader type Writer type Closer type Seeker type Re

上位机的poke()、peek()、写SPI函数实现以及控制信息的发送(VRT Context包)

lib/usrp/common/fifo_ctrl_excelsior.cpp /******************************************************************* * Peek and poke 32 bit implementation ******************************************************************/ void poke32(wb_addr_type addr, boos

使用golang的pprof包对程序进行性能分析

程序经常出现OOM错误,然后关键字"go pprof"搜到文章<Go程序性能分析pprof>,该文章第二步说运行程序后会生成profile文件,但是编译运行后发现生成的profile文件大小一直为0,然后关键字"go pprof profile is empty"搜到文章<Golang pprof heap profile is empty>,该文章说在运行程序前添加环境变量GODEBUG="memprofilerate=1&quo

Golang Gin 项目包依赖管理 godep 使用

Golang Gin 项目包依赖管理 godep 使用 标签(空格分隔): Go 在按照github.com/tools/godep文档go get完包以后,调整项目结构为$GOPATH/src/$PROJECT_NAME/,同时使项目编译没有问题.执行godep save命令,出现了一系列包缺失的问题: github.com/campoy/embedmd github.com/client9/misspell/cmd/misspell github.com/dustin/go-broadcas

Golang官方log包详解

Golang官方log包详解 以下全是代码, 详解在注释中, 请从头到尾看 // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package log implements a simple logging package. I

聊聊golang的context

golang的context的主要用途在于在多个goroutine之间传递数据,管理多个goroutine的生命周期.实际的应用场景有比如,在http服务中,每个请求就对应一个goroutine,而请求之中可能又会调用别的api,而产生更多的goroutine,用context来管理这些goroutine就能比较方便在这些goroutine中传递数据和管理. 主要方法 func Background() Context Background() 返回一个空的context,这是一个根节点. fu