Если ваша цель - прочитать только один результат, а затем отменить другие запросы, попробуйте что-то вроде этого:
func fetch(urls []string) *http.Response {
ch := make(chan *http.Response)
defer close(ch)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
for _, url := range urls {
go func(ctx context.Context, url string) {
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
resp, err := http.Do(req)
if err == nil {
select {
case ch <- resp:
case <- ctx.Done():
}
}
}(ctx, url)
}
return <-ch
}
При этом используется контекст с возможностью отмены, поэтому после возврата первого результата оставшийся httpзапросы сигнализируются об отмене.
ПРИМЕЧАНИЕ: Ваш код содержит ошибку, которую я исправил выше:
func _, url := range urls {
go func() {
http.Do(url) // `url` is changed here on each iteration through the for loop, meaning you will not be calling the url you expect
}()
}
Исправьте это, передав url
для функции goroutine вместо использования замыкания:
func _, url := range urls {
go func(url string) {
http.Do(url) // `url` is now safe
}(url)
}
Связанный пост: Почему golang не выполняет итерацию правильно в цикле for с диапазоном?