Implementando tiempos de espera en Go con canales

Beginner

This tutorial is from open-source community. Access the source code

Introducción

El propósito de este laboratorio es implementar los tiempos de espera en Go utilizando canales y select.

Tiempos de espera

Los tiempos de espera son importantes para los programas que se conectan a recursos externos o que de otra manera necesitan limitar el tiempo de ejecución. En este laboratorio, se implementarán tiempos de espera en Go utilizando canales y select.

  • Implementar tiempos de espera en Go utilizando canales y select.
  • Utilizar un canal con búfer para evitar fugas de gorutinas en caso de que el canal nunca se lea.
  • Utilizar time.After para esperar a que se envíe un valor después del tiempo de espera.
  • Utilizar select para continuar con la primera recepción lista.
## Ejecutar este programa muestra que la primera operación
## agota el tiempo y la segunda tiene éxito.
$ go run timeouts.go
timeout 1
result 2

A continuación, se muestra el código completo:

// Los _tiempos de espera_ son importantes para los programas
// que se conectan a recursos externos o que de otra manera
// necesitan limitar el tiempo de ejecución. Implementar
// tiempos de espera en Go es fácil y elegante gracias a
// los canales y `select`.

package main

import (
    "fmt"
    "time"
)

func main() {

    // Para nuestro ejemplo, supongamos que estamos
    // ejecutando una llamada externa que devuelve su
    // resultado en un canal `c1` después de 2s. Tenga en
    // cuenta que el canal tiene búfer, por lo que el envío
    // en la gorutina no bloquea. Este es un patrón común
    // para evitar fugas de gorutinas en caso de que el
    // canal nunca se lea.
    c1 := make(chan string, 1)
    go func() {
        time.Sleep(2 * time.Second)
        c1 <- "result 1"
    }()

    // Aquí está el `select` que implementa un tiempo de
    // espera. `res := <-c1` espera el resultado y
    // `<-time.After` espera a que se envíe un valor
    // después del tiempo de espera de 1s. Dado que
    // `select` continúa con la primera recepción lista,
    // tomaremos el caso de tiempo de espera si la
    // operación tarda más de los 1s permitidos.
    select {
    case res := <-c1:
        fmt.Println(res)
    case <-time.After(1 * time.Second):
        fmt.Println("timeout 1")
    }

    // Si permitimos un tiempo de espera más largo de 3s,
    // entonces la recepción de `c2` tendrá éxito y
    // mostraremos el resultado.
    c2 := make(chan string, 1)
    go func() {
        time.Sleep(2 * time.Second)
        c2 <- "result 2"
    }()
    select {
    case res := <-c2:
        fmt.Println(res)
    case <-time.After(3 * time.Second):
        fmt.Println("timeout 2")
    }
}

Resumen

En este laboratorio, aprendimos cómo implementar tiempos de espera en Go utilizando canales y select. Utilizamos un canal con búfer para evitar fugas de gorutinas en caso de que el canal nunca se lea, y time.After para esperar a que se envíe un valor después del tiempo de espera. También utilizamos select para continuar con la primera recepción lista.