golang基础-网络请求WithTimeout、上下文withValue、withCancel、WithDeadline
来源:互联网 发布:linux可以用网银吗 编辑:程序博客网 时间:2024/06/14 23:08
- 网络请求超时控制
- 上下文WithValue
- 超时控制WithDeadline
- WithCancel
在 Go http包的Server中,每一个请求在都有一个对应的 goroutine 去处理。请求处理函数通常会启动额外的 goroutine 用来访问后端服务,比如数据库和RPC服务。用来处理一个请求的 goroutine 通常需要访问一些与请求特定的数据,比如终端用户的身份认证信息、验证相关的token、请求的截止时间。 当一个请求被取消或超时时,所有用来处理该请求的 goroutine 都应该迅速退出,然后系统才能释放这些 goroutine 占用的资源。
在Google 内部,开发了 Context 包,专门用来简化 对于处理单个请求的多个 goroutine 之间与请求域的数据、取消信号、截止时间等相关操作,这些操作可能涉及多个 API 调用。你可以通过 go get golang.org/x/net/context 命令获取这个包。本文要讲的就是如果使用这个包,同时也会提供一个完整的例子。
Context interface
网络请求超时控制
type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() error Value(key interface{}) interface{}}
Deadline()返回一个time.Time,是当前 Context 的应该结束的时间,ok 表示是否有 deadlineDone()返回一个struct{}类型的只读 channelErr()返回 Context 被取消时的错误Value(key interface{}) 是 Context 自带的 K-V 存储功能
package mainimport ( "context" "fmt" "io/ioutil" "net/http" "time")type Result struct { r *http.Response err error}func process() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) //释放资源 defer cancel() tr := &http.Transport{} client := &http.Client{Transport: tr} resultChan := make(chan Result, 1) //发起请求 req, err := http.NewRequest("GET", "http://www.baidu.com", nil) if err != nil { fmt.Println("http request failed, err:", err) return } /* func (c *Client) Do(req *Request) (*Response, error) */ go func() { resp, err := client.Do(req) pack := Result{r: resp, err: err} //将返回信息写入管道(正确或者错误的) resultChan <- pack }() select { case <-ctx.Done(): tr.CancelRequest(req) er:= <-resultChan fmt.Println("Timeout!",er.err) case res := <-resultChan: defer res.r.Body.Close() out, _ := ioutil.ReadAll(res.r.Body) fmt.Printf("Server Response: %s", out) } return}func main() { process()}
输出如下:
如果修改下代码
req, err := http.NewRequest("GET", "http://google.com", nil)
请求超时,输出log信息如下
PS E:\golang\go_pro\src\safly> go build main.goPS E:\golang\go_pro\src\safly> main.exeTimeout! Get http://google.com: net/http: request canceled while waiting for connectionPS E:\golang\go_pro\src\safly>
上下文WithValue
package mainimport ( "context" "fmt")func process(ctx context.Context) { ret,ok := ctx.Value("trace_id").(int) if !ok { ret = 21342423 } fmt.Printf("ret:%d\n", ret) s , _ := ctx.Value("session").(string) fmt.Printf("session:%s\n", s)}func main() { ctx := context.WithValue(context.Background(), "trace_id", 13483434) ctx = context.WithValue(ctx, "session", "sdlkfjkaslfsalfsafjalskfj") process(ctx)}
输出如下:
PS E:\golang\go_pro\src\safly> go run main.goret:13483434session:sdlkfjkaslfsalfsafjalskfjPS E:\golang\go_pro\src\safly>
超时控制WithDeadline
package mainimport ( "context" "fmt" "time")func main() { d := time.Now().Add(4 * time.Second) //50毫秒到了,触发如下代码 ctx, cancel := context.WithDeadline(context.Background(), d) defer cancel() select { case <-time.After(3 * time.Second): fmt.Println("overslept") case <-ctx.Done(): //50毫秒到了,执行该代码 fmt.Println(ctx.Err()) }}
输出如下:
PS E:\golang\go_pro\src\safly> go run deadline.gooversleptPS E:\golang\go_pro\src\safly>
如果将上面代码修改为
func main() { d := time.Now().Add(4 * time.Second) //50毫秒到了,触发如下代码 ctx, cancel := context.WithDeadline(context.Background(), d) defer cancel() select { case <-time.After(5 * time.Second): fmt.Println("overslept") case <-ctx.Done(): //50毫秒到了,执行该代码 fmt.Println(ctx.Err()) }}
然后在执行输出如下:
PS E:\golang\go_pro\src\safly> go run deadline.gocontext deadline exceededPS E:\golang\go_pro\src\safly>
WithCancel
我们来了解一个利用context结束goroutine的demo
package mainimport ( "context" "fmt" "time")/* 创建一个管道chan,启动goroutine for循环存数据**/func gen(ctx context.Context) <-chan int { dst := make(chan int) n := 1 go func() { for { select { case <-ctx.Done(): //执行defer cancel操作后,就会执行到该select入库 fmt.Println("i exited") return // returning not to leak the goroutine case dst <- n: n++ } } }() return dst}func test() { ctx, cancel := context.WithCancel(context.Background()) //当取数据n == 5时候,执行defer cancel操作 defer cancel() intChan := gen(ctx) for n := range intChan { fmt.Println(n) if n == 5 { break } }}func main() { test() time.Sleep(time.Hour)}
输出如下:
PS E:\golang\go_pro\src\safly> go run cancle.go12345i exited
阅读全文
0 0
- golang基础-网络请求WithTimeout、上下文withValue、withCancel、WithDeadline
- golang context.WithTimeout 超时处理
- Golang 基础 HTTP请求
- 关于golang的context.WithTimeout的cancel的说明
- Golang爬虫基础:GET请求
- Golang爬虫基础:POST请求
- 应用上下文&请求上下文
- golang-context(上下文管理)
- 网络请求基础
- 请求上下文
- Golang爬虫基础:通过代理IP发送请求
- golang基础-服务端、客户端VS服务端、TCP请求数据
- 程序上下文context for golang
- swift基础值网络请求
- AsyncTask基础运用(请求网络)
- golang基础
- Golang 基础
- 显式传参 vs. 请求上下文
- ubuntu常用功能安装集锦
- 机器学习_谱聚类
- BZOJ2829: 信用卡凸包(圆的凸包)
- Visual Studio 2010读写ini文件(1)读出ini文件所有键名、节名、键值
- C++ tuple 元组合并与排序
- golang基础-网络请求WithTimeout、上下文withValue、withCancel、WithDeadline
- 深度学习基础总结
- 请求数据版购物车
- 在移动和PC自适应页面做视频弹窗控制小案例
- NuGet Package Explorer上传时报:failed to process request:'Method Not Allowed'错误解决办法
- 基于IntelliJ IDEA打包JavaFX
- C++信息学奥赛一本通题库1035 等差数列末项计算
- Android自定义拦截器+展示数据+弹出框
- 平面扫描