You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
4.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package goConcurrency
import (
"context"
"fmt"
"strings"
"sync"
"time"
)
func ContextCancelDeep() {
// 1. 创建层级关系的cancelCtx
//ctxOne, _ := context.WithCancel(context.Background())
//ctxTwo, cancel := context.WithCancel(ctxOne)
//ctxThree, _ := context.WithCancel(ctxOne)
//ctxFour, _ := context.WithCancel(ctxTwo)
// 定时器方式保证取消
ctxOne, _ := context.WithTimeout(context.Background(), 1*time.Second)
ctxTwo, cancel := context.WithTimeout(ctxOne, 1*time.Second)
ctxThree, _ := context.WithTimeout(ctxOne, 1*time.Second)
ctxFour, _ := context.WithTimeout(ctxTwo, 1*time.Second)
wg := sync.WaitGroup{}
// 2. 使用gorutine来接收ctx.Done()
wg.Add(4)
go func(c context.Context) {
defer wg.Done()
select {
case <-c.Done(): // ctxOne
fmt.Println("one cancel")
}
}(ctxOne)
go func(c context.Context) {
defer wg.Done()
select {
case <-c.Done(): // ctxTwo
fmt.Println("two cancel")
}
}(ctxTwo)
go func(c context.Context) {
defer wg.Done()
select {
case <-c.Done(): // ctxThree
fmt.Println("three cancel")
}
}(ctxThree)
go func(c context.Context) {
defer wg.Done()
select {
case <-c.Done(): // ctxFour
fmt.Println("four cancel")
}
}(ctxFour)
// 主动取消
cancel()
wg.Wait()
}
func ContextCancelTime() {
// 1. 创建带有时间的cancelContext
//ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
// deadline
//ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(2*time.Second))
//curr := time.Now()
//ctx, cancel := context.WithDeadline(context.Background(), time.Date(curr.Year(), curr.Month(), curr.Day(), 20, 30, 0, 0, time.Local))
wg := sync.WaitGroup{}
wg.Add(4)
// 2. 启动goroutine携带cancelCtx
for i := 0; i < 4; i++ {
// 启动goroutine携带ctx参数
go func(c context.Context, n int) {
defer wg.Done()
// 监听context的取消完成channel来确定是否执行了主动cancel操作
for {
select {
// 等待接收c.Done()这个channel
case <-c.Done():
fmt.Println("Cancel")
return
default:
}
fmt.Println(strings.Repeat(" ", n), n)
time.Sleep(300 * time.Millisecond)
}
}(ctx, i)
}
// 3. 主动取消 cancel() 和到时取消
select {
// 4s后主动取消 cancel()
case <-time.NewTimer(4 * time.Second).C:
cancel() // ctx.Done() <- time.Now
fmt.Println("call cancel() Cancel")
case <-ctx.Done(): // 2s后到时取消
fmt.Println("main Cancel")
}
wg.Wait()
}
func ContextCancelCall() {
// 1. 创建cancelContext
ctx, cancel := context.WithCancel(context.Background())
wg := sync.WaitGroup{}
wg.Add(4)
// 2. 启动goroutine携带cancelCtx
for i := 0; i < 4; i++ {
// 启动goroutine携带ctx参数
go func(c context.Context, n int) {
defer wg.Done()
// 监听context的取消完成channel来确定是否执行了主动cancel操作
for {
select {
// 等待接收c.Done()这个channel
case <-c.Done():
fmt.Println("Cancel")
return
default:
}
fmt.Println(strings.Repeat(" ", n), n)
time.Sleep(300 * time.Millisecond)
}
}(ctx, i)
}
// 3. 主动取消 cancel()
// 3s后取消
select {
case <-time.NewTimer(2 * time.Second).C:
cancel() // ctx.Done() <- time.Now
}
select {
case <-ctx.Done():
fmt.Println("main Cancel")
}
wg.Wait()
}
type MyContextKey string
func ContextValue() {
wg := sync.WaitGroup{}
// 1. 创建带有value的Context
ctx := context.WithValue(context.Background(), MyContextKey("title"), "Go of MSB")
// 2. 将ctx传递到goroutine中使用
wg.Add(1)
go func(c context.Context) {
defer wg.Done()
// 获取key对应的value
if v := c.Value(MyContextKey("title")); v != nil {
fmt.Println("Found value: ", v)
return
}
fmt.Println("Key not found:", MyContextKey("title"))
}(ctx)
wg.Wait()
}
func ContextValueDeep() {
wg := sync.WaitGroup{}
// 1. 创建带有value的Context
ctxOne := context.WithValue(context.Background(), "title", "Go of One")
//ctxTwo := context.WithValue(ctxOne, "title", "Go of Two")
ctxTwo := context.WithValue(ctxOne, "key", "Go of Two")
//ctxThree := context.WithValue(ctxTwo, "title", "Go of Three")
ctxThree := context.WithValue(ctxTwo, "key", "Go of Three")
// 2. 将ctx传递到goroutine中使用
wg.Add(1)
go func(c context.Context) {
defer wg.Done()
// 获取key对应的value
if v := c.Value("title"); v != nil {
fmt.Println("Found value: ", v)
return
}
fmt.Println("Key not found:", "title")
}(ctxThree)
wg.Wait()
}