-2

假设我的程序中有一个全球客户。在这个程序中,我有几个 goroutine 向同一个全局客户端发出请求。例如net/http

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)
    }
}

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

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

4

1 回答 1

2

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

如果你想为某些 goroutine 修改客户端,不需要使用单个客户端,你可以为每个 goroutine 创建一个新的客户端。

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

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

于 2021-08-28T05:13:12.017 回答