es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Imprima un contador preciso en Golang mientras se utilizan goroutines.

Así que tengo mis goroutines configuradas que están acelerando mis solicitudes en la función request. Estoy tratando de implementar un contador que cuente cuántas solicitudes se han enviado, pero como las goroutines sortean ‘repetir’ el proceso x cantidad de veces, es difícil hacer un contador preciso. ¿Hay otro método o alguien sabe una forma de registrar con precisión la cantidad de solicitudes enviadas?

Código:

func routine() {
    fmt.Println()
    rep := 1000
    results := make(chan string)

    for i := 0; i < rep; i++ {
        go func(num int) {
            results <- request(num)
        }(i)
    }

    for i := 0; i < rep; i++ {
        fmt.Println(<-results)
    }
}

...

func request(num int) string {
    client := &http.Client{}
    count_checks := 0

    for {
        req, err := http.NewRequest("GET", "https://endpoint.com/users", nil)

        resp, err := client.Do(req)
        if err != nil {
            print(err)
        }

        defer resp.Body.Close()
        contents, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            fmt.Printf("%s", err)
            os.Exit(1)
        }

        if contents != nil {
            count_checks++
            fmt.Println(count_checks)
        }
    }
}

Lo cual tiene una salida esperada (1000 veces por número):

1
1
1
Tags:  ,

Answer

  1. Avatar for davy.ai

    Una posible solución es agregar una variable de contador global e incrementarla cada vez que se envía una solicitud, utilizando un mutex lock para acceder de manera segura al contador desde múltiples goroutines. Aquí tienes un ejemplo:

    var counter int
    var mutex sync.Mutex
    
    func routine() {
        rep := 1000
        results := make(chan string)
    
        for i := 0; i < rep; i++ {
            go func(num int) {
                results <- request(num)
            }(i)
        }
    
        for i := 0; i < rep; i++ {
            fmt.Println(<-results)
        }
    
        fmt.Printf("Total de solicitudes enviadas: %d\n", counter)
    }
    
    func request(num int) string {
        client := &http.Client{}
    
        for {
            req, err := http.NewRequest("GET", "https://endpoint.com/users", nil)
    
            resp, err := client.Do(req)
            if err != nil {
                print(err)
            }
    
            defer resp.Body.Close()
            _, err = ioutil.ReadAll(resp.Body)
            if err != nil {
                fmt.Printf("%s", err)
                os.Exit(1)
            }
    
            // Incrementar de manera segura el contador
            mutex.Lock()
            counter++
            mutex.Unlock()
        }
    
        return ""
    }
    

    De esta manera, la variable global counter se incrementa cada vez que se envía una solicitud, independientemente de cuántas veces se llame a la función request dentro de una goroutine. El bloqueo del mutex mutex asegura que la operación de incremento sea segura para subprocesos y evita condiciones de carrera. Después de enviar todas las solicitudes, la función routine puede mostrar el número total de solicitudes enviadas.

Comments are closed.