Как я могу сделать запрос на множественные и получить ответ с Goroutines - PullRequest
0 голосов
/ 29 июня 2018

Мне нужно сделать несколько запросов в URL и получить возврат и сохранить в части возврата, чтобы работать позже, но это не работает мой код:

func main() {
requestTestGoRoutine()
log.Println("END")
}

func requestTestGoRoutine() {
    done := make(chan *http.Response)
    defer close(done)
    for _, r := range requests {
        go execute(r, done)
        var p protocol
        resp := <-done
        json.NewDecoder(resp.Body).Decode(&p)
        fmt.Println("protocol:", p)
        protocols = append(protocols, p)

    }
    fmt.Println("protocols:", protocols)
}

func execute(r map[string]interface{}, done chan *http.Response) {
    bodyRequest := new(bytes.Buffer)
    json.NewEncoder(bodyRequest).Encode(r)
    log.Println("Fazendo request...")
    resp, err := requestControlTower(url, bodyRequest)
    if err != nil {
        log.Fatal(err)
    }
    done <- resp
}

мой вывод в терминале:

2018/06/29 16:10:26 Fazendo request...
protocol: {123456 Aprovado}
2018/06/29 16:10:38 Fazendo request...
protocol: {123457 Aprovado}
2018/06/29 16:10:48 Fazendo request...
protocol: {123458 Aprovado}
2018/06/29 16:10:58 Fazendo request...
protocol: {123459 Aprovado}
2018/06/29 16:11:08 Fazendo request...
protocol: {123410 Aprovado}
2018/06/29 16:11:18 Fazendo request...
protocol: {123411 Aprovado}
protocols: [{123456 Aprovado} {123457 Aprovado} {123458 Aprovado} {123459         
Aprovado} {123410 Aprovado} {123411 Aprovado}]
2018/06/29 16:11:29 END

Кто-нибудь может мне помочь?

1 Ответ

0 голосов
/ 01 июля 2018

Причина, по которой ваш код обрабатывает только один запрос за раз, заключается в том, что вы ожидаете ответа от своего канала в цикле запросов:

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 в этот мьютекс, чтобы предотвратить одновременную запись в журнал нескольких процедур, что может привести к перепутыванию строк в вашем журнале.

У меня нет доступа ко всему вашему коду, так что это не проверено. Если что-то не работает, не стесняйтесь, дайте мне знать в комментарии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...