将单个 http 客户端用于多个 goroutine 时,在一个线程上编辑传输会影响另一个线程吗?

While using a single http client for several goroutines, does editing the transport on one thread affect the other?

假设我有一个全局 net/http client in my program. Within this program, I have several goroutines making requests with the same global client。例如

Golang 伪代码:

package main

func editTransportAndFetch(c *http.Client) {
    c.Transport = &http.Transport{
        // Make some unique change here
    }
    c.Get("https://www.google.com")
}

func main() {
    client := http.Client
    
    // Spawns 10 processes
    for i := 0; i < 10; i++ {
        go editTransportAndFetch(client)
    }
}

在这个伪代码示例中,我演示了生成正在编辑的 http.Transport 的 10 个进程。在本例中,进行了完全相同的更改,因此干扰可能不是什么大问题。但是,无论如何,如果这些进程同时发生,更新全局客户端传输的一个进程是否会干扰另一进程可能正在使用的传输?

我的最终用例是我想要一个全球客户并能够指定自定义 DialTLSContext 但仅限于某些请求。我不想同时使用 DialTLSContext 的请求也可能是 运行。我担心如果我编辑一个请求的客户端的 http.Transport 它可能会干扰并导致另一个请求也使用 DialTLSContext 即使我不'想要它。

如果您在多个 goroutine 之间共享同一个客户端实例,并且如果您从其中一个 goroutine 修改该客户端,则行为未定义,因为它是数据竞争。

如果要修改部分goroutine的client,不需要单独使用一个client,可以为每个goroutine新建一个client。

如果你想在 main 中配置一个客户端,并将其用作所有 goroutines 的模板,按值传递客户端,而不是 *client,因此该模板的副本将传递给每个 goroutine,每个 goroutine 都会在自己的副本上工作,共享下面的公共 Transport。如果您将 Transport 设置为其他内容,那么由于 Client 是一个副本,它仍然是安全的。

但是,如果您在 Transport 实例(RoundTripper)中修改某些内容,这又是一个竞争条件。不要那样做。