1. Test example analysis
example_test.go, shows 4 examples of the With-series
func ExampleWithCancel() { gen := func(ctx ) <-chan int { dst := make(chan int) n := 1 go func() { for { select { case <-(): return // returning not to leak the goroutine case dst <- n: n++ } } }() return dst } ctx, cancel := (()) defer cancel() // cancel when we are finished consuming integers for n := range gen(ctx) { (n) if n == 5 { break } } // Output: // 1 // 2 // 3 // 4 // 5 }
Structural analysis,gen
is a function, the return value is a channel,for range channel
It has special significance. For will loop to read data from the channel until the channel is closed(), otherwise it will be an infinite loop.
Coroutines inside gen are typical closures. For range will constantly trigger reading, and for select will continuously trigger writing. After the main coroutine is read 5 times, the main function will be terminated and the defer function will be triggered, that is, cancel the corresponding callback of the operation. At this time, the done channel will be closed, and the coroutines inside gen will exit normally.
This example is to test the context of the cancel signal, and the cancel function call is placedmain
ofdefer
in the function.
const shortDuration = 1 * func ExampleWithDeadline() { d := ().Add(shortDuration) ctx, cancel := ((), 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 <-(1 * ): ("overslept") case <-(): (()) } // Output: // context deadline exceeded }
deadline
This example ofmain
ofdefer
There are also active calls to cancel functions in it. In fact, printing can show whether deadline works as expected.
func ExampleWithTimeout() { ctx, cancel := ((), shortDuration) defer cancel() select { case <-(1 * ): ("overslept") case <-(): (()) // prints "context deadline exceeded" } // Output: // context deadline exceeded }
timeout
onlydeadline
A abbreviation of .
func ExampleWithValue() { type favContextKey string f := func(ctx , k favContextKey) { if v := (k); v != nil { ("found value:", v) return } ("key not found:", k) } k := favContextKey("language") ctx := ((), k, "Go") f(ctx, k) f(ctx, favContextKey("color")) // Output: // found value: Go // key not found: color }
and
()
It is an access operation. When fetching, if the key is not found, nil will be returned.
2. Unit Testing
context_text.go,x_test.go
It's unit test, example_test.go
It is an example, benchmark_test.go is a benchmark, and net_test.go shows deadline support for net packages.
Let’s first look at the context_text.go of the unit test.
type testingT interface {} type otherContext struct {} func quiescent(t testingT) {} 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) {}
Most of the parameter types of test functions exposed are testT interface types, but this source file is not implementedtestingT
Interface,
func TestBackground(t *) { XTestBackground(t) } func TestTODO(t *) { XTestTODO(t) } func TestWithCancel(t *) { XTestWithCancel(t) } func TestParentFinishesChild(t *) { XTestParentFinishesChild(t) } func TestChildFinishesFirst(t *) { XTestChildFinishesFirst(t) } func TestDeadline(t *) { XTestDeadline(t) } func TestTimeout(t *) { XTestTimeout(t) } func TestCanceledTimeout(t *) { XTestCanceledTimeout(t) } func TestValues(t *) { XTestValues(t) } func TestAllocs(t *) { XTestAllocs(t, , ) } func TestSimultaneousCancels(t *) { XTestSimultaneousCancels(t) } func TestInterlockedCancels(t *) { XTestInterlockedCancels(t) } func TestLayersCancel(t *) { XTestLayersCancel(t) } func TestLayersTimeout(t *) { XTestLayersTimeout(t) } func TestCancelRemoves(t *) { XTestCancelRemoves(t) } func TestWithCancelCanceledParent(t *) { XTestWithCancelCanceledParent(t) } func TestWithValueChecksKey(t *) { XTestWithValueChecksKey(t) } func TestInvalidDerivedFail(t *) { XTestInvalidDerivedFail(t) } func TestDeadlineExceededSupportsTimeout(t *) { XTestDeadlineExceededSupportsTimeout(t) } func TestCustomContextGoroutines(t *) { XTestCustomContextGoroutines(t) }
This isx_test.go
The content is directly usedType to implement the testingT interface.
Let’s first analyze the implementation of the testingT interface.
type T struct { common isParallel bool context *testContext } func (t *T) Deadline() (deadline , ok bool) { deadline = return deadline, !() }
Notice:No implementation type, Deadline() returns the deadline information stored in it.
Embedded, most of the method sets come to 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()
Is it fromImplementation: When a test case is repeatedly executed multiple times, concurrent parameters can be enabled.
This is the end of this article about the detailed analysis of Go context test source code. For more relevant Go context test source code analysis content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!