Go语言-Context上下文实践

使用 Context 的程序包需要遵循如下的原则来满足接口的一致性以及便于静态分析

1.不要把 Context 存在一个结构体当中,显式地传入函数。Context 变量需要作为第一个参数使用,一般命名为ctx

2.即使方法允许,也不要传入一个 nil 的 Context ,如果你不确定你要用什么 Context 的时候传一个 context.TODO

3.使用 context 的 Value 相关方法只应该用于在程序和接口中传递的和请求相关的元数据,不要用它来传递一些可选的参数

4.同样的 Context 可以用来传递到不同的 goroutine 中,Context 在多个goroutine 中是安全的

方法说明

  • Done 方法在Context被取消或超时时返回一个close的channel,close的channel可以作为广播通知,告诉给context相关的函数要停止当前工作然后返回。

当一个父operation启动一个goroutine用于子operation,这些子operation不能够取消父operation。下面描述的WithCancel函数提供一种方式可以取消新创建的Context.

Context可以安全的被多个goroutine使用。开发者可以把一个Context传递给任意多个goroutine然后cancel这个context的时候就能够通知到所有的goroutine。

  • Err方法返回context为什么被取消。
  • Deadline返回context何时会超时。
  • Value返回context相关的数据。
  • context 包已经给我们提供了两个,一个是 Background(),一个是 TODO(),这两个函数都会返回一个 Context 的实例。只是返回的这两个实例都是空 Context。BackGound是所有Context的root,不能够被cancel。

实例1

这个例子传递一个上下文,它有一个任意的截止期,它告诉一个阻塞函数,一旦它到达它,它就应该放弃它的工作。

package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    d := time.Now().Add(50 * time.Millisecond)
    ctx, cancel := context.WithDeadline(context.Background(),d)
    // Even though ctx will be expired, it is good practice to call its
    // cancelation function in any case. Failure to do so may keep the
    // context and its parent alive longer than necessary.
    defer cancel()
    select {
        case <- time.After(1 * time.Second):
            fmt.Println("overslept")
        case <- ctx.Done():
            fmt.Println(ctx.Err())
    }
}

运行结果

context deadline exceeded

实例2

package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    d := time.Now().Add(50 * time.Second)
    ctx, cancel := context.WithDeadline(context.Background(),d)
    // Even though ctx will be expired, it is good practice to call its
    // cancelation function in any case. Failure to do so may keep the
    // context and its parent alive longer than necessary.
    defer cancel()
    select {
        case <- time.After(1 * time.Second):
            fmt.Println("overslept")
        case <- ctx.Done():
            fmt.Println(ctx.Err())
    }
}

运行结果

overslept

实例3

package main

import (
    "context"
    "fmt"
)

func main() {
    // gen generates integers in a separate goroutine and
    // sends them to the returned channel.
    // The callers of gen need to cancel the context once
    // they are done consuming generated integers not to leak
    // the internal goroutine started by gen.
    gen := func(ctx context.Context) <-chan int {
            dst := make(chan int)
            n := 1
            go func() {
        for {
            select {
                case <-ctx.Done():
                    return // returning not to leak the goroutine
                case dst <- n:
                    n++
            }
        }
            }()

            return dst
    }

    ctx, cancel := context.WithCancel(context.Background())
    defer cancel() // cancel when we are finished consuming integers

    for n := range gen(ctx) {
        fmt.Println(n)
        if n == 5 {
            break
        }
    }
}

运行结果

1
2
3
4
5

实例4

package main

import (
    "fmt"
    "context"
)

func main() {
    type favContextKey string

    f := func(ctx context.Context, k favContextKey) {
        if v := ctx.Value(k); v != nil {
            fmt.Println("found value:", v)
            return
        }
        fmt.Println("key not found:", k)
    }

    k := favContextKey("language")
    ctx := context.WithValue(context.Background(), k, "Go")
    f(ctx, k)
    f(ctx, favContextKey("color"))
}

运行结果

found value: Go
key not found: color

实例5

package main

import (
    "fmt"
    "context"
)

func main() {

    f := func(ctx context.Context, k string) {
        if v := ctx.Value(k); v != nil {
            fmt.Println("found value:", v)
            return
        }
        fmt.Println("key not found:", k)
    }

    ctx := context.WithValue(context.Background(), "language", "Go")
    f(ctx, "language")
    f(ctx, "color")
}

运行结果

found value: Go
key not found: color

原文地址:http://blog.51cto.com/12880687/2130374

时间: 2024-11-08 21:50:37

Go语言-Context上下文实践的相关文章

OBJECTIVE-C语言的最佳实践和高阶技术期刊OBJC的章节目录

CSDN博客: forlong401 邮件地址:[email protected] 微博:@forlong401 第一章 轻量级视图控制器 第一节.介绍 第二节.轻量级视图控制器 [Chris Eidhof] 第三节.清理表视图的代码[Florian Kugler] 第四节.测试试图控制器[Daniel Eggert] 第五节.视图控制器容器[Ricki Gregersen] 第二章 并发编程 第一节.编辑语 第二节.并发编程:API接口和挑战[Florian Kugler] 第三节.一般的后台

探寻ASP.NET MVC鲜为人知的奥秘(3):寻找多语言的最佳实践方式

如果你的网站需要被世界各地的人访问,访问者会使用各种不同的语言和文字书写习惯,那么创建一个支持多语言的网站就是十分必要的了,这一篇文章就讲述怎么快速合理的创建网站对多语言的支持.接下来通过一个实例来讲述实践方式. 首先创建一个ASP.NET MVC5应用程序,命名为Internationalization: 然后在Models中添加一个示例的模型类: public class Employee { [Display(Name = "Name", ResourceType = typeo

Context上下文

Context上下文通俗含义: Context上下文主要用来从上文传播对象到下文中,他是可以跨线程的. 就是说  class A中你把一个OBJ对象存放到了上下文容器中, 然后你以后的所有线程或你以下调用的所有类中都可以从上下文容器中取出 上面再class A中存放的OBJ对象. 目前了解: 1:图形上下文 2:托管对象上下文 3:HttpContext上下文

支持“***Context”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269)。

在用VS进行MVC开发的过程中遇到如下问题: 支持“***Context”上下文的模型已在数据库创建后发生更改.请考虑使用 Code First 迁移更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269). 解决了,把数据库中检测模型变化的表(如上图所示)删除就可以了

(转载)java context上下文,通俗易懂

转载自http://blog.csdn.net/xiaokui008/article/details/8454949 Context在Java中的出现是如此频繁,但其中文翻译"上下文"又是如此诡异拗口,因此导致很多人不是很了解Context的具体含义是指什么,所以很有必要来深究一下这词的含义.先来举几个JAVA中用到Context的例子(1)JNDI的一个类javax.naming.InitialContext,它读取JNDI的一些配置信息,并内含对象和其在JNDI中的注册名称的映射信

context 上下文对象

最近学习中经常看到Context,没能明白中文含义,一番搜索后看到此文,颇为实在,特转之 Context在Java中的出现是如此频繁,但其中文翻译"上下文"又是如此诡异拗口,因此导致很多人不是很了解Context的具体含义是指什么,所以很有必要来深究一下这词的含义.先来举几个JAVA中用到Context的例子 (1)JNDI的一个类javax.naming.InitialContext,它读取JNDI的一些配置信息,并内含对象和其在JNDI中的注册名称的映射信息.请看下面的代码 Ini

Android Context 上下文 你必须知道的一切

http://blog.csdn.net/lmj623565791/article/details/40481055/ 本文大多数内容翻译自:http://www.doubleencore.com/2013/06/context/  我重新组织了下内容以及结构,建议大家尽可能看下原文. 1.Context概念 其实一直想写一篇关于Context的文章,但是又怕技术不如而误人子弟,于是参考了些资料,今天准备整理下写出来,如有不足,请指出,参考资料会在醒目地方标明. Context,相信不管是第一天

context上下文 php版解释

context翻译为上下文其实不是很好,只是翻译理解大概的作用,对于开发来说,context是一对定义的使用的变量,常量或者说是配置, 部分的函数功能除了缺省值之外,往往需要手动设置一些定义量来配合当前语境,来适配开发者想法的需求,这些可以适配其他方法或者函数的 定义量就是context,数据来源有可能是变量,也可能是数据流,这些函数是为了适应更多其他函数调用或者方便开发者使用操作函数, 让开发者配合当前语境来设置,比如stream_context_create 通过设置选项来让file_get

web中几个context上下文的理解

在 java 中, 常见的 Context 有很多, 像: ServletContext, ActionContext, ServletActionContext, ApplicationContext, PageContext, SessionContext ... 那么, Context 究竟是什么东西呢? 直译是上下文.环境的意思.比如像: "今天我收到了一束花, 男朋友送的!" 又或者 "今天我收到了一束花, 送花的人送错了的!" 同样是收到一束花, 在不同