go协程上下文context

context
context1.17

上下文解决的问题

  • 协程间的通信
channel
contextcontext.withvalue()channel
  • 子协程的超时处理
context

上下文的几个方法和用法

context.withcancel(context.context)
withcancel()context.background()cancal()
package main
​
import (
    "context"
    "fmt"
    "time"
)
func worker(ctx context.context) {
    for {
        select {
        case <-ctx.done():
            return
        default:
        }
        fmt.println("worker...")
        time.sleep(time.second * 1)
    }
}
func main() {
    ctx, cancal := context.withcancel(context.background())
    go worker(ctx)
    time.sleep(time.second * 5)
    cancal()
    fmt.println("over ...")
​
}
context.withtimeout(context.context,timeout)
cancel()cancel()
package main
​
import (
    "context"
    "fmt"
    "time"
)
​
func worker(ctx context.context) {
    for {
        select {
        case <-ctx.done():
            return
        default:
        }
        fmt.println("worker...")
        time.sleep(time.second * 1)
    }
}
​
func main() {
    ctx, cancal := context.withtimeout(context.background(), time.second*2)
    go worker(ctx)
    time.sleep(time.second * 5)
    cancal()
    fmt.println("over ...")
​
}
context.withdeadline(context.context,(绝对时间)timeout)
timeoutcancel()cancel()
package main
​
import (
    "context"
    "fmt"
    "time"
)
​
func worker(ctx context.context) {
    for {
        select {
        case <-ctx.done():
            return
        default:
        }
        fmt.println("worker...")
        time.sleep(time.second * 1)
    }
}
​
func main() {
    ctx, cancal := context.withdeadline(context.background(), time.now().add(3 * time.second))
    go worker(ctx)
    time.sleep(time.second * 5)
    cancal()
    fmt.println("over ...")
​
}
context.withvalue()

先看一下这段代码

package main
​
import (
    "context"
    "fmt"
    "time"
)
​
type ctxkey string
​
func worker(ctx context.context) {
    // 在子协程中获取上下文信息
    num, ok := ctx.value(ctxkey("num")).(string)
    if !ok {
        fmt.println("invalid trace code")
    }
    fmt.println(num)
    for {
        select {
        case <-ctx.done():
            return
        default:
        }
        fmt.println("worker...")
        time.sleep(time.second * 1)
    }
}
​
func main() {
    ctx, cancal := context.withdeadline(context.background(), time.now().add(3*time.second))
    // 利用上下文传一个 num = 1234567
    // 实例化一个上下文
    ctx = context.withvalue(ctx, ctxkey("num"), "1234567")
    go worker(ctx)
    time.sleep(time.second * 5)
    cancal()
    fmt.println("over ...")
}

通过上下文实现协程间的通信,如果项目大,为了避免变量的污染,原则上:上下文通信所用的key需要自定义一个类型

type tracecode string;context.withvalue(context.context,key,value)