• 有趣的 Go HttpClient 超时机制


    hello,大家好呀,我是既写 Java 又写 Go 的小楼,在写 Go 的过程中经常对比这两种语言的特性,踩了不少坑,也发现了不少有意思的地方,今天就来聊聊 Go 自带的 HttpClient 的超时机制。

    Java HttpClient 超时底层原理

    在介绍 Go 的 HttpClient 超时机制之前,我们先看看 Java 是如何实现超时的。

    写一个 Java 原生的 HttpClient,设置连接超时、读取超时时间分别对应到底层的方法分别是:

    再追溯到 JVM 源码,发现是对系统调用的封装,其实不光是 Java,大部分的编程语言都借助了操作系统提供的超时能力。

    然而 Go 的 HttpClient 却提供了另一种超时机制,挺有意思,我们来盘一盘。但在开始之前,我们先了解一下 Go 的 Context。

    Go Context 简介

    Context 是什么?

    根据 Go 源码的注释:

    // A Context carries a deadline, a cancellation signal, and other values across
    // API boundaries.
    // Context’s methods may be called by multiple goroutines simultaneously.

    Context 简单来说是一个可以携带超时时间、取消信号和其他数据的接口,Context 的方法会被多个协程同时调用。

    Context 有点类似 Java 的ThreadLocal,可以在线程中传递数据,但又不完全相同,它是显示传递,ThreadLocal 是隐式传递,除了传递数据之外,Context 还能携带超时时间、取消信号。

    Context 只是定义了接口,具体的实现在 Go 中提供了几个:

    • Background :空的实现,啥也没做
    • TODO:还不知道用什么 Context,先用 TODO 代替,也是啥也没做的空 Context
    • cancelCtx:可以取消的 Context
    • timerCtx:主动超时的 Context

    针对 Context 的三个特性,可以通过 Go 提供的 Context 实现以及源码中的例子来进一步了解下。

    Context 三个特性例子

    这部分的例子来源于 Go 的源码,位于 src/context/example_test.go

    携带数据

    使用 context.WithValue 来携带,使用 Value 来取值,源码中的例子如下:

    // 来自 src/context/example_test.go
    func ExampleWithValue() {
       
    	type favContextKey string
    
    	f := func(ctx context.Context, k favContextKey) {
       
    		if v := ctx.Value(k); v != nil {
       
    			fmt.Println("found value:", v)
    			return
    		}
    		fmt.Println("key not found:", k)
    	}
    
    	k := favContextKey("language")
    	ctx := context.WithValue(context.Background(), k, "Go")
    
    	f(ctx, k)
    	f(ctx, favContextKey("color"))
    
    	// Output:
    	// found value: Go
    	// key not found: color
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    取消

    先起一个协程执行一个死循环,不停地往 channel 中写数据,同时监听 ctx.Done() 的事件

    // 来自 src/context/example_test.go
    gen := func(ctx context.Context) <-chan int {
       
    		dst := make(chan int)
    		n := 1
    		go func() {
       
    			for {
       
    				select {
       
    				<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    linux 环境下 分布式文件搭建fastDFS
    用proteus直接仿真stm32-可以完全丢弃编程器
    SQLite 命令行客户端 + HTA 实现简易UI
    鸿蒙应用开发之环境搭建
    ES5中实现继承
    Python基于Flask的高校舆情分析,舆情监控可视化系统
    大数据培训教程Combiner合并
    Immutable学习之路----告别传统拷贝
    JAVA经典百题之排序算法
    记一次Tomcat卡死在 Deploying web application 步骤的问题
  • 原文地址:https://blog.csdn.net/lkxiaolou/article/details/127872127