Golang Go语言 context 简介(1)

Golang Go语言 context 简介(1)

这个系列主要聊下 context 的出发点,带来了哪些便利的地方,常用 API,以及源代码分析

很多童鞋忽略的问题

API 服务是很多童鞋开发过的套路,从 API 取得数据或者控制字段,查询数据库返回业务数据。 那好,问题来了,如果 http client(curl 或者浏览器)在数据没有返回的过程中,异常中止了。你的 API 服务是不是还在傻傻的查询呢? 先来个伪代码模拟,下面会用 fmt.Printf+time.Sleep 模拟数据库查询操作。

package main

import ( “fmt” “github.com/gin-gonic/gin” “time” )

func main() {

router := gin.Default()
router.POST("/", func(c *gin.Context) {

    //模拟操作数据库
    for i := 0; i < 200; i++ {
        fmt.Printf("read db\n")
        time.Sleep(time.Second * 1)
    }
})  

router.Run()

} // curl -X POST 127.0.0.1:8080/ // 你会发现如果客户段 ctrl+c 后,还会不停打印 read db,直到计算器结束。

调研 http.Request 数据结构

上面的资源浪费有没有办法优化?先瞄下 http.Request 源代码。好像有个 context 的东西还挺有意思的。

type Request struct {
    // ctx is either the client or server context. It should only
    // be modified via copying the whole Request using WithContext.
    // It is unexported to prevent people from using Context wrong
    // and mutating the contexts held by callers of the same request.
    ctx context.Context
}

// Context returns the request’s context. To change the context, use // WithContext. // // The returned context is always non-nil; it defaults to the // background context. // // For outgoing client requests, the context controls cancelation. // // For incoming server requests, the context is canceled when the // client’s connection closes, the request is canceled (with HTTP/2), // or when the ServeHTTP method returns. func (r *Request) Context() context.Context { if r.ctx != nil { return r.ctx } return context.Background() }

改造资源浪费代码

package main

import ( “fmt” “github.com/gin-gonic/gin” “time” )

func main() {

router := gin.Default()
router.POST("/", func(c *gin.Context) {

    //模拟操作数据库
    ctx := c.Request.Context()
    for i := 0; i < 200; i++ {
        select {
        case <-ctx.Done(): // 新增加的关键代码
            fmt.Printf("found client ctrl+c\n")
            return
        default:
            fmt.Printf("read db\n")
        }
        time.Sleep(time.Second * 1)
    }
})

router.Run()

}

// curl -X POST 127.0.0.1:8080/ // 你会发现如果客户段 ctrl+c 后,已经不打印出来 read db。

ok,完美解决资源浪费的问题。 还有更多玩法,下篇介绍。

我的 github

https://github.com/guonaihong/gout


更多关于Golang Go语言 context 简介(1)的实战教程也可以访问 https://www.itying.com/category-94-b0.html

13 回复

request with context go1.7 出的功能 是很好用

更多关于Golang Go语言 context 简介(1)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的好用,最重要的是 context 已经被官方扶正,后面一些并发套路都要用 context 的设计模式了。

一个连续的过程该等多久还是得等多久,比如同步查数据库要花 10 分

楼主的语文需要重修。

可有重修的门路?

兄弟,没太明白提出的问题。。。

赞,昨天因为在自己写接口的时候发现读库的时候有个 query 跟 quertContext 两个方法,于是去查了一下 context 的相关知识,只是有了解还不太会用

其实我一直没有理解 TODO 以及 backGround 两个使用的特点,什么时候用哪个

todo 就是暂时作为父 context 后续可能会改,另一个就是父 context 不会改了


从实现上来看没啥区别,都是从 emptyCtx 构造出来。更多的区别还是字面意思。
go<br>var (<br> background = new(emptyCtx)<br> todo = new(emptyCtx)<br>)<br><br>// Background returns a non-nil, empty Context. It is never canceled, has no<br>// values, and has no deadline. It is typically used by the main function,<br>// initialization, and tests, and as the top-level Context for incoming<br>// requests.<br>func Background() Context {<br> return background<br>}<br><br>// TODO returns a non-nil, empty Context. Code should use context.TODO when<br>// it's unclear which Context to use or it is not yet available (because the<br>// surrounding function has not yet been extended to accept a Context<br>// parameter).<br>func TODO() Context {<br> return todo<br>}<br>

楼主以前是不是写 PHP 的啊?

以前写 linux c 的。怎么了?

以下是对“Golang Go语言 context 简介”的回复:

在Go语言中,context(上下文)是一个非常重要的概念,它主要用于在多个goroutine之间传递请求特定任务的截止日期、取消信号以及其他请求范围的值。

context本质上是一个接口,定义了四个方法:Deadline()、Done()、Err()和Value(key interface{})。通过这四个方法,context可以在goroutine之间传递控制信号和数据,实现任务的同步、取消和超时控制等功能。

在实际应用中,context的使用非常广泛。例如,在处理HTTP请求时,可以使用context来传递请求的截止日期和取消信号,以便在请求处理过程中及时响应客户端的取消操作或超时限制。此外,在数据库操作中,context也可以用来控制查询的超时时间和取消操作,以避免资源占用过多和数据库连接泄漏等问题。

context的创建和传递也非常灵活。可以通过context.Background()或context.TODO()创建一个空的context作为根节点,然后通过context.WithCancel()、context.WithDeadline()和context.WithTimeout()等方法创建带有取消功能、截止日期或超时限制的子context,并将它们传递给需要的goroutine。

总之,context是Go语言中处理并发编程时非常有用的工具,它可以帮助开发者更好地管理goroutine之间的控制信号和数据传递,提高程序的可靠性和可维护性。

回到顶部