美文网首页
Go context

Go context

作者: xyz098 | 来源:发表于2019-05-22 15:52 被阅读0次
goroutine要处理的问题?
  • 数据共享
  • 释放回收

github练习代码

context doc blog
解决的问题

why:go服务每个进来的请求都有一个goroutine。请求可能是访问数据库或者RPC服务,当请求取消或超时时,所有的goroutine应该快速回收各自使用的资源。

what:context package处理一个请求的 请求作用域值value、取消Done()、超时Deadline()

Go http的请求,每个请求对应一个goroutine处理,此时该处理函数会启动额外的goroutine处理其他数据,如:数据库和rpc服务。

  1. 当子的goroutine访问时需要用到父goroutine数据时,可以用context保存。
  2. 当父goroutine被取消或超时时,所有子goroutine都应该退出,释放资源。可以用context的Done()处理。
代码思路梳理
  • server

    对于客户端的每个请求创建上下文对象,并设置超时时间context.WithTimeout(context.Background(), timeout)

    解析userIP,设置为上下文 userip.NewContext(ctx, userIP) ,google搜索用到上下文 google.Search(ctx, query)

    var (
          ctx    context.Context
          cancel context.CancelFunc
      )
    timeout, err := time.ParseDuration(req.FormValue("timeout"))
    if err == nil {
      ctx, cancel = context.WithTimeout(context.Background(), timeout) // 创建context
    } else {
      ctx, cancel = context.WithCancel(context.Background())
    }
    defer cancel() 
    
    ctx = userip.NewContext(ctx, userIP)    // 使用context传递
    ...
    results, err := google.Search(ctx, query)
    
  • userip

    在context中设置共享值context.WithValue(ctx, userIPKey, userIP),获取值ctx.Value(userIPKey).(net.IP)

    func NewContext(ctx context.Context, userIP net.IP) context.Context {
      return context.WithValue(ctx, userIPKey, userIP)      // 设置值
    }
    
    func FromContext(ctx context.Context) (net.IP, bool) {
      userIP, ok := ctx.Value(userIPKey).(net.IP)         // 获取值
      return userIP, ok
    }
    
  • google

    并发一个请求完成搜索go func() { c <- f(client.Do(req)) }(),保证父退出时,子goroutine退出 case <-ctx.Done():

    if userIP, ok := userip.FromContext(ctx); ok {
          q.Set("userip", userIP.String())
    }
    
    func httpDo(ctx context.Context, req *http.Request, f func(*http.Response, error) error) error {
      tr := &http.Transport{}
      client := &http.Client{Transport: tr}
      c := make(chan error, 1)
      go func() { c <- f(client.Do(req)) }()    // 启动goroutine
      select {
      case <-ctx.Done():                        // 保证父退出时,子goroutine退出
          tr.CancelRequest(req)
          <-c // Wait for f to return.
          return ctx.Err()
      case err := <-c:
          return err
      }
    } 
    
原文:Go Concurrency patterns:context
翻译:Go语言并发模型:使用 context
简书:如何使用context

相关文章

  • GO 语言context.Context类型

    context.Context类型 context.Context类型(以下简称Context类型)是在Go 1....

  • Golang Context 详细原理和使用技巧

    Golang Context 详细原理和使用技巧 Context 背景 和 适用场景 Context 的背景 Go...

  • go context

    Req-->a-->c--->b---->return (链式调用) 链式调用和我们普通的函数调用是存在差别的:函...

  • Go context

    goroutine要处理的问题? 数据共享 释放回收 github练习代码 context doc blog...

  • Go context

    Go context 在RPC或者Web服务中,当Server端接受一个request的时候,都会开启一个额外的g...

  • Go context

    控制并发有两种经典的方式:WaitGroup和Context WaitGroup:控制多个Goroutine同时完...

  • go context

    context 很重要,总体作用就是 设置程序执行的 deadline 设置程序的截止日期 status...

  • go context

    https://zhuanlan.zhihu.com/p/110085652

  • go context

    [TOC]相信大家在日常工作开发中一定会看到这样的代码: context被当作第一个参数(官方建议),并且不断透传...

  • Go Context的踩坑经历

    转载 Go Context 踩坑经历

网友评论

      本文标题:Go context

      本文链接:https://www.haomeiwen.com/subject/ytsuzqtx.html