Причина, по которой ваш код обрабатывает только один запрос за раз, заключается в том, что вы ожидаете ответа от своего канала в цикле запросов:
resp := <-done
Мне гораздо проще работать с группами ожидания и мьютексами, чем с каналами, поэтому я использую их в своем примере:
var protocolsMutex sync.Mutex
var wg sync.WaitGroup
func main() {
requestTestGoRoutine()
log.Println("END")
}
func requestTestGoRoutine() {
for _, r := range requests {
wg.Add(1)
go execute(r)
}
wg.Wait()
fmt.Println("protocols:", protocols)
}
func execute(r map[string]interface{}, done chan *http.Response) {
defer wg.Done()
bodyRequest := new(bytes.Buffer)
json.NewEncoder(bodyRequest).Encode(r)
resp, _ := requestControlTower(url, bodyRequest)
var p protocol
json.NewDecoder(resp.Body).Decode(&p)
protocolsMutex.Lock()
log.Println("Fazendo request...")
protocols = append(protocols, p)
protocolsMutex.Unlock()
}
Здесь для каждого запроса в цикле запросов в requestTestGoRoutine()
я увеличиваю sync.WaitGroup
на единицу и запускаю процедуру execute
для запроса. В функции execute
я запускаю defer wg.Done()
, что приведет к уменьшению группы ожидания на единицу, как только вернется программа.
После цикла запросов я запускаю wg.Wait()
, который будет ждать, пока все программы вызовут wg.Done()
, прежде чем печатать срез protocols
.
A sync.Mutex
используется для управления доступом к срезу protocols
, так что только одна процедура может получить к нему доступ одновременно. Если мьютекс заблокирован, другие программы будут ждать, пока он не будет разблокирован, прежде чем перейти к следующему разделу кода. Без мьютекса, более одного goroutine могли писать в срез одновременно, вызывая состояние гонки. Я также переместил оператор log.Println
в этот мьютекс, чтобы предотвратить одновременную запись в журнал нескольких процедур, что может привести к перепутыванию строк в вашем журнале.
У меня нет доступа ко всему вашему коду, так что это не проверено. Если что-то не работает, не стесняйтесь, дайте мне знать в комментарии.