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.

El caso por defecto en una declaración select se comporta casi como bloqueante.

He notado un comportamiento extraño que no es del todo obvio al usar una sentencia select dentro de un loop, por ejemplo, si tengo:

package main

import (
    "fmt"
    "time"
)

func main() {
    done := make(chan bool)

    go func() {
        fmt.Println("here we go")
        for {
            select {
            case <-done:
                fmt.Println("Bye")
                return
            default:
                fmt.Println("esto debería continuar imprimiéndose")
            }
            fmt.Println("loop continues")
        }
    }()

    time.Sleep(2 * time.Second)
    done <- true
}

Yo asumiría que el caso default solo se imprimirá por no más de 2 segundos, sin embargo, este no es el caso, por lo menos en mi CPU dura alrededor de 10 segundos antes de ver el mensaje de Bye.

Sin embargo, si agrego time.Sleep(1 * time.Second) justo después de “loop continues” Está más o menos en sincronía con el sueño de 2 segundos antes de done <- true.

Dado esto, mi suposición es que las llamadas de impresión se están apilando y el tiempo prolongado de finalización se debe a que la pila de llamadas tarda más tiempo en pasar. ¿Es esta una descripción correcta de lo que está sucediendo? ¿O me falta algo más obvio?

Edit: Para poner mi hipótesis a prueba, hice esto y ahora funciona como se esperaba, tarda 2 segundos en finalizar el programa:

go func() {
    fmt.Println("here we go")
    for {
        select {
        case <-done:
            fmt.Println("Bye")
            return
        default:
        }
    }
}()
Tags:  , ,

Answer

  1. Avatar for davy.ai

    Parece que tu hipótesis es correcta. Cuando la instrucción select se encuentra dentro de un bucle y se activa el caso default, las llamadas a fmt.Println se amontonan y el programa tarda más en completarse.

    Agregar un time.Sleep(1 * time.Second) justo después de “el bucle continúa” parece funcionar porque le da tiempo a las llamadas a fmt.Println para completarse antes de que continúe el bucle.

    Alternativamente, como has mostrado en tu edición, eliminar las llamadas a fmt.Println dentro del bucle y dejarlas solo dentro del caso done donde se recibe el canal también funciona y asegura que el programa finalice de manera oportuna.

Comments are closed.