这个系列主要聊下 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 源代码。好像有个 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,完美解决资源浪费的问题。 还有更多玩法,下篇介绍。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.