Go语言context test源码分析详情

 更新时间:2022年02月09日 09:20:10   作者:zwf193071   
这篇文章主要介绍了Go语言context test源码分析详情,关于context test,测试对象是context包,测试包的包名是context_test,下面将对context test源码进行分析,需要的朋友可以参考一下,希望对你有所帮助

1.测试例子分析

example_test.go,展示了With-系列的4个例子

func ExampleWithCancel() {
  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
    }
  }
  // Output:
  // 1
  // 2
  // 3
  // 4
  // 5
}

结构分析,gen是一个函数,返回值是一个信道, for range channel是有特殊意义的, for会循环从channel读数据,直到channel被close(),不然就是无限循环.

gen内部的协程就是典型的闭包,for range会不断触发读,gen内部的for select 会不断触发写,主协程读5次之后,会结束main函数,会触发defer函数, 也就是取消操作对应的回调,此时done信道会被close,gen内部的协程会正常退出.

这个例子是测试支持取消信号的上下文,取消函数的调用放在了maindefer函数中.

const shortDuration = 1 * time.Millisecond
func ExampleWithDeadline() {
  d := time.Now().Add(shortDuration)
  ctx, cancel := context.WithDeadline(context.Background(), d)

  // Even though ctx will be expired, it is good practice to call its
  // cancellation 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())
  }

  // Output:
  // context deadline exceeded
}

deadline的这个例子,在maindefer中也有主动调用取消函数的. 实际上通过打印可以显示deadline是否按预期工作.

func ExampleWithTimeout() {
  ctx, cancel := context.WithTimeout(context.Background(), shortDuration)
  defer cancel()

  select {
  case <-time.After(1 * time.Second):
    fmt.Println("overslept")
  case <-ctx.Done():
    fmt.Println(ctx.Err()) // prints "context deadline exceeded"
  }

  // Output:
  // context deadline exceeded
}

timeout只是deadline的一种简写.

func ExampleWithValue() {
  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"))

  // Output:
  // found value: Go
  // key not found: color
}

context.WithValueContext.Value()是存取操作, 取的时候,如果key没找到,会返回nil.

2.单元测试

context_text.go,x_test.go是单元测试, example_test.go是示例,benchmark_test.go是基准测试, net_test.go展示了deadline对net包的支持.

先看单元测试的context_text.go.

type testingT interface {}

type otherContext struct {}
func quiescent(t testingT) time.Duration {}
func XTestBackground(t testingT) {}
func XTestTODO(t testingT) {}
func XTestWithCancel(t testingT) {}
func contains(m map[canceler]struct{}, key canceler) bool {}
func XTestParentFinishesChild(t testingT) {}
func XTestChildFinishesFirst(t testingT) {}
func testDeadline(c Context, name string, t testingT) {}
func XTestDeadline(t testingT) {}
func XTestTimeout(t testingT) {}
func XTestCanceledTimeout(t testingT) {}
func XTestValues(t testingT) {}
func XTestAllocs(t testingT, testingShort func() bool, testingAllocsPerRun func(int, func()) float64) {}
func XTestSimultaneousCancels(t testingT) {}
func XTestInterlockedCancels(t testingT) {}
func XTestLayersCancel(t testingT) {}
func XTestLayersTimeout(t testingT) {}
func XTestCancelRemoves(t testingT) {}
func XTestWithCancelCanceledParent(t testingT) {}
func XTestWithValueChecksKey(t testingT) {}
func XTestInvalidDerivedFail(t testingT) {}
func recoveredValue(fn func()) (v interface{}) {}
func XTestDeadlineExceededSupportsTimeout(t testingT) {}
type myCtx struct {}
type myDoneCtx struct {}
func (d *myDoneCtx) Done() <-chan struct{} {}
func XTestCustomContextGoroutines(t testingT) {}

这暴露的大多测试函数的参数类型是testingT接口类型,但这个源文件中没有实现testingT接口的,

func TestBackground(t *testing.T)                      { XTestBackground(t) }
func TestTODO(t *testing.T)                            { XTestTODO(t) }
func TestWithCancel(t *testing.T)                      { XTestWithCancel(t) }
func TestParentFinishesChild(t *testing.T)             { XTestParentFinishesChild(t) }
func TestChildFinishesFirst(t *testing.T)              { XTestChildFinishesFirst(t) }
func TestDeadline(t *testing.T)                        { XTestDeadline(t) }
func TestTimeout(t *testing.T)                         { XTestTimeout(t) }
func TestCanceledTimeout(t *testing.T)                 { XTestCanceledTimeout(t) }
func TestValues(t *testing.T)                          { XTestValues(t) }
func TestAllocs(t *testing.T)                          { XTestAllocs(t, testing.Short, testing.AllocsPerRun) }
func TestSimultaneousCancels(t *testing.T)             { XTestSimultaneousCancels(t) }
func TestInterlockedCancels(t *testing.T)              { XTestInterlockedCancels(t) }
func TestLayersCancel(t *testing.T)                    { XTestLayersCancel(t) }
func TestLayersTimeout(t *testing.T)                   { XTestLayersTimeout(t) }
func TestCancelRemoves(t *testing.T)                   { XTestCancelRemoves(t) }
func TestWithCancelCanceledParent(t *testing.T)        { XTestWithCancelCanceledParent(t) }
func TestWithValueChecksKey(t *testing.T)              { XTestWithValueChecksKey(t) }
func TestInvalidDerivedFail(t *testing.T)              { XTestInvalidDerivedFail(t) }
func TestDeadlineExceededSupportsTimeout(t *testing.T) { XTestDeadlineExceededSupportsTimeout(t) }
func TestCustomContextGoroutines(t *testing.T)         { XTestCustomContextGoroutines(t) }

这是x_test.go的内容,直接是用testing.T类型来实现testingT接口.

那先分析一下testing.T对testingT接口的实现.

type T struct {
  common
  isParallel bool
  context    *testContext
}
func (t *T) Deadline() (deadline time.Time, ok bool) {
  deadline = t.context.deadline
  return deadline, !deadline.IsZero()
}

注意:testing.T.context不是context.Context的实现类型, Deadline()返回了t.context中存储的deadline信息.

testing.T内嵌了testing.common,大部分方法集都来至common:

Error(args ...interface{})
Errorf(format string, args ...interface{})
Fail()
FailNow()
Failed() bool
Fatal(args ...interface{})
Fatalf(format string, args ...interface{})
Helper()
Log(args ...interface{})
Logf(format string, args ...interface{})
Name() string
Skip(args ...interface{})
SkipNow()
Skipf(format string, args ...interface{})
Skipped() bool

Parallel()是由testing.T实现,某个测试用例多次重复执行时, 可启用并发参数.

到此这篇关于Go语言context test源码分析详情的文章就介绍到这了,更多相关Go语言context test源码分析内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang map与sync.map的异同详解

    Golang map与sync.map的异同详解

    在Go语言中,map和sync.Map都是用于存储键值对的数据结构,但它们在并发安全性、性能和使用场景上存在显著差异,接下来将深入探讨这两种数据结构的异同,感兴趣的朋友可以参考下
    2024-01-01
  • Go语言操作mysql数据库简单例子

    Go语言操作mysql数据库简单例子

    这篇文章主要介绍了Go语言操作mysql数据库简单例子,本文包含插入数据和查询代码实例,需要的朋友可以参考下
    2014-10-10
  • Go高级特性探究之HTTP错误处理详解

    Go高级特性探究之HTTP错误处理详解

    在Web应用程序中,HTTP错误处理是非常重要的,它关系到Web应用程序的稳定性和可靠性,本文介绍如何在Go项目中处理HTTP错误,并提供相应的解决方案和实践经验,希望对Go语言Web应用程序的开发者有所帮助
    2023-06-06
  • go-cqhttp智能聊天功能的实现

    go-cqhttp智能聊天功能的实现

    这篇文章主要介绍了go-cqhttp智能聊天功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • golang通过反射设置结构体变量的值

    golang通过反射设置结构体变量的值

    这篇文章主要介绍了golang通过反射设置结构体变量的值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Golang使用lua脚本实现redis原子操作

    Golang使用lua脚本实现redis原子操作

    这篇文章主要介绍了Golang使用lua脚本实现redis原子操作,本文通过实例代码给大家介绍的非常详细,对大家的工作或学习具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • 详解在Go语言单元测试中如何解决文件依赖问题

    详解在Go语言单元测试中如何解决文件依赖问题

    现如今的 Web 应用程序往往采用 RESTful API 接口形式对外提供服务,后端接口直接向前端返回 HTML 文件的情况越来越少,所以在程序中操作文件的场景也变少了,在编写单元测试时,文件就成了被测试代码的外部依赖,本文就来讲解下测试过程中如何解决文件外部依赖问题
    2023-08-08
  • Golang利用channel协调协程的方法详解

    Golang利用channel协调协程的方法详解

    go 当中的并发编程是通过goroutine来实现的,利用channel(管道)可以在协程之间传递数据,所以本文就来讲讲Golang如何利用channel协调协程吧
    2023-05-05
  • Golang 在gin框架中如何使用JWT鉴权

    Golang 在gin框架中如何使用JWT鉴权

    JWT,全称 JSON Web Token,是一种开放标准(RFC 7519),用于安全地在双方之间传递信息,这篇文章主要介绍了golang 在Gin框架中使用JWT鉴权,需要的朋友可以参考下
    2024-07-07
  • Go语言基础类型及常量用法示例详解

    Go语言基础类型及常量用法示例详解

    这篇文章主要为大家介绍了Go语言基础类型及常量的用法及示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-11-11

最新评论