Ако http.Client вече се споделя от паралелни заявки, дръжте полето Transport стабилно. Обвивката може да синхронизира кой напълно конфигуриран транспорт получава всеки следващ обмен:

type routeSlot struct {
    mu sync.RWMutex
    current http.RoundTripper
}

func (s *routeSlot) RoundTrip(r *http.Request) (*http.Response, error) {
    s.mu.RLock()
    current := s.current
    s.mu.RUnlock()
    return current.RoundTrip(r)
}

func (s *routeSlot) Set(next http.RoundTripper) {
    s.mu.Lock()
    s.current = next
    s.mu.Unlock()
}

С net/http и sync го инициализирайте, преди да публикувате клиента:

slot := &routeSlot{current: initialTransport}
client := &http.Client{Transport: slot}

slot.Set(nextTransport)

initialTransport и nextTransport трябва да са не-nil, напълно конфигурирани и безопасни при паралелност изпълнители на обмен. Изграждайте всеки прокси транспорт, преди да го публикувате, и не променяйте конфигурацията му, докато заявките го използват.

Заключването пази само снимката на указателя, така че бавна заявка не държи маршрутизиращото заключване през целия си мрежов обмен. Заявка, която вече използва предишната снимка, продължава по този транспорт; превключването не я пуска наново и не мести връзката ѝ.

Запазвайте и извеждайте старите транспорти през ограничения жизнен цикъл на приложението, като позволявате на текущата работа да завърши и затваряте неактивните пулове, когато е уместно. Пренасочване може да предизвика още един RoundTrip след превключване. Ако цял работен поток изисква един маршрут, задайте го на границата на работния поток, вместо да променяте този споделен селектор по средата.

Подобни статии