Contexto corrutina de Golang

¡Acostúmbrate a escribir juntos! Este es el noveno día de mi participación en el "Nuggets Daily New Plan · April Update Challenge", haz clic para ver los detalles del evento .

ir al contexto coroutinecontext

golang se contextusa principalmente para transferir información de contexto entre goroutines, que incluye: señal de cancelación, tiempo de espera, fecha límite, kv, etc.

contextEs una característica que salió después de la 1.17versión golang.

Problemas resueltos por contexto

  1. Comunicación entre rutinas

Por ejemplo, en una aplicación web, cada solicitud es manejada por una rutina. Por supuesto, para esta corrutina que procesa solicitudes, generalmente iniciamos otras corrutinas para manejar otros servicios, como operaciones de base de datos, autenticación, lectura y escritura de archivos, etc. Estas corrutinas son independientes y no podemos percibir cómo se ejecutan otras corrutinas en la corrutina actual. El canal de utilidad channelpuede realizar la función de comunicación.

contextEn context.WithValue()esencia, channella comunicación también se logra a través de

  1. Manejo de tiempo de espera de subrutinas

De manera similar, en las aplicaciones web, nuestro proceso principal siempre reside en la memoria. Cada solicitud es procesada por una corrutina. En el proceso de procesamiento comercial, se puede iniciar otra corrutina para procesar otros servicios. Cuando la subrutina es anormal o está bloqueada, es imposible retroalimentar información a la corrutina de nivel superior. la rutina principal se bloqueará si no recibe retroalimentación. El contexto puede resolver este problema muy bien y contextpuede darse cuenta del tiempo de espera o la salida del tiempo de la subrutina o corrutina descendiente.

Varios métodos y usos del contexto.

context.WithCancel(context.Context)

WithCancel()El método pasa una instancia de contexto vacía, que se puede usar directamente context.Background(), y devuelve un contexto y una función de cancelación. La llamada cancal()pasará señales a otras corrutinas, y las subrutinas se pueden cerrar o procesar después de recibir la señal.

package main
​
import (
    "context"
    "fmt"
    "time"
)
func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
func main() {
    ctx, cancal := context.WithCancel(context.Background())
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
​
}
​
复制代码

context.WithTimeout(context.Context,timeout)

Defina un contexto que expirará. Después de la creación de instancias, comenzará la cuenta regresiva. Cuando llegue el momento, la cancel()función se llamará automáticamente para notificar a la subrutina, o la cancel()notificación se puede llamar manualmente. Si hay subrutinas en la subrutina, continúe usando este contexto, cuando la corrutina principal envíe una señal de cancelación, todos los que usen este contexto serán notificados.

package main
​
import (
    "context"
    "fmt"
    "time"
)
​
func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
​
func main() {
    ctx, cancal := context.WithTimeout(context.Background(), time.Second*2)
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
​
}
​
复制代码

context.WithDeadline(context.Context,(绝对时间)timeout)

Defina un contexto que expirará, la Timeoutdiferencia es que el tiempo transcurrido es un tiempo absoluto. Cuando se alcance el tiempo especificado, la cancel()función se llamará automáticamente para notificar a la subrutina, o la cancel()notificación se puede llamar manualmente. Si hay subrutinas en la subrutina, continúe usando este contexto, cuando la corrutina principal envíe una señal de cancelación, todos los que usen este contexto serán notificados.

package main
​
import (
    "context"
    "fmt"
    "time"
)
​
func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
​
func main() {
    ctx, cancal := context.WithDeadline(context.Background(), time.Now().Add(3 * time.Second))
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
​
}
​
复制代码

Comunicación de contexto entre rutinas:context.WithValue()

Echa un vistazo a este código primero

package main
​
import (
    "context"
    "fmt"
    "time"
)
​
type CTXKEY string
​
func worker(ctx context.Context) {
    // 在子协程中获取上下文信息
    num, ok := ctx.Value(CTXKEY("num")).(string)
    if !ok {
        fmt.Println("invalid trace code")
    }
    fmt.Println(num)
    for {
        select {
        case <-ctx.Done():
            return
        default:
        }
        fmt.Println("worker...")
        time.Sleep(time.Second * 1)
    }
}
​
func main() {
    ctx, cancal := context.WithDeadline(context.Background(), time.Now().Add(3*time.Second))
    // 利用上下文传一个 num = 1234567
    // 实例化一个上下文
    ctx = context.WithValue(ctx, CTXKEY("num"), "1234567")
    go worker(ctx)
    time.Sleep(time.Second * 5)
    cancal()
    fmt.Println("over ...")
}
​
复制代码

La comunicación entre rutinas se realiza a través del contexto.Si el proyecto es grande, para evitar la contaminación de variables, en principio: la clave utilizada para la comunicación contextual necesita personalizar un tipo

type traceCode string;context.WithValue(context.Context,key,value)

Supongo que te gusta

Origin juejin.im/post/7084613288104820773
Recomendado
Clasificación