Zusammenfassung der Nutzungsszenarien von Context in Golang

Wenn die in go 1.7 eingeführte übergeordnete Coroutine die untergeordnete Coroutine schließen möchte, wird die Abbruchfunktion ihres Kontexts aufgerufen, die ein Signal an ihren Kanal sendet.

Die Funktion des Kontexts kann in zwei Aspekten widergespiegelt werden: Senden von Beendigungssignalen an Methoden und Übergeben einiger gemeinsamer Daten an mehrere Methoden.

Die vier Hauptstrukturen von Context sind die Verwendung von CancelContext, TimeoutContext, DeadLineContext und ValueContext

Welche anwendbaren Szenarien gibt es?

Aus irgendeinem Grund (Zeitüberschreitung oder erzwungenes Beenden) möchten wir die Berechnungsaufgabe dieser Goroutine abbrechen, dann können wir diesen Kontext verwenden

Gemeinsame Komponenten zur Parallelitätskontrolle: waitGroup, Context

Spezifische Nutzungsszenarien:

1. RPC-Nutzung, http-Anfrage. In einer Kategorie zusammengefasst sind Zeitüberschreitungen bei Verwendung von withCancel. cancel() wird mehrmals aufgerufen und der Aufruf von cancel im Kontextpaket ist idempotent. Sie können es bedenkenlos mehrmals aufrufen. Asynchrone Parallelsteuerung: Wenn ein bestimmter Anruf fehlschlägt, sind andere Anrufe nicht betroffen

Codebeispiel

package main

import (
    "context"
    "fmt"
    "math/rand"
    "net/http"
    "os"
    "time"
)

func main(){
//context控制并发  WithCancel  cancel()
    ctx,cancel := context.WithCancel(context.Background())
   go Worker(ctx,"01")
   go Worker(ctx,"02")
   go Worker(ctx,"03")
    time.Sleep(time.Second * 5)
    fmt.Println("stop all")
    cancel()
    time.Sleep(time.Second * 1)
}

func Worker(ctx context.Context,name string ) {
    for {
        select{
        case <- ctx.Done():
            fmt.Println(name," stop the goroutine!")
            return
        default:
            fmt.Println(name," ing")
            time.Sleep(time.Second *1)
        }
    }
}

//结果打印:
//01  ing
//02  ing
//02  ing
//03  ing
//01  ing
//01  ing
//02  ing
//03  ing
//02  ing
//01  ing
//03  ing
//01  ing
//02  ing
//03  ing
//stop all
//02  stop the goroutine!
//03  stop the goroutine!
//01  stop the goroutine!

context WithCancel bricht die Steuerung ab und sendet ein Abbruchsignal, um sicherzustellen, dass alle von dieser Logik ausgehenden Goroutinen erfolgreich abgebrochen werden.

2. HTTP-Serveranforderungen übertragen Daten untereinander. WithContext wird häufig in Interceptoren verwendet. Nach der Cookie-Verifizierung werden die öffentlichen Informationen in der Anfrage gespeichert und die Schnittstelle kann sie selbst abrufen.

Codebeispiel

// WithValue 使用
func main(){
    ContextWithValue()
}

func ContextWithValue() {
    rand.Seed(time.Now().Unix())
    ctx := context.WithValue(context.Background(), keyID, rand.Int())
    operation1(ctx)
}

func operation1(ctx context.Context) {
    fmt.Println("operation1 for id:", ctx.Value(keyID), " completed")
    operation2(ctx)
}

func operation2(ctx context.Context) {
    fmt.Println("operation2 for id:", ctx.Value(keyID), " completed")
}

3. Timeout-Anfrage. rpc ruft http auf und ruft WithTimeout WithDeadLine auf (zeitaufwändige Vorgänge wie Datei-IO oder Netzwerk-IO können prüfen, ob die verbleibende Zeit ausreicht, um zu entscheiden, ob mit dem nächsten Schritt fortgefahren werden soll.)

Die in WithDeadLine und withTimeout übergebenen Zeitparameter sind unterschiedlich, der Rest ist jedoch gleich.

WithTimeout-Codebeispiel

import (
    "context"
    "fmt"
    "math/rand"
    "net/http"
    "os"
    "time"
)


// WithTimeout
func main(){
// 创建一个空ctx
    ctx := context.Background()
    // 设置超时时间
    cxt, _ := context.WithTimeout(ctx, 1*time.Millisecond)

    start := time.Now()
    // 创建一个请求 访问谷歌
    req, _ := http.NewRequest(http.MethodGet, "http://baidu.com", nil)
    // 将带有取消方法的ctx和请求关联
    req = req.WithContext(cxt)

    client := &http.Client{}
    res, err := client.Do(req)
    if err!=nil{
        fmt.Println("Request failed:", err ," time ",time.Now().Sub(start))

        return
    }
    fmt.Println("Response received, status code:", res.StatusCode)
}
WithTimeout代码示例
func main(){
    ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second * 4))
    defer cancel()
    copyFileWithDeadline(ctx)
    time.Sleep(time.Second * 5)
}

func copyFileWithDeadline(ctx context.Context)  {
    deadline, ok := ctx.Deadline()
    if ok == false {
        return
    }
    // deadline.Sub(time.Now()) 截止时间与当前时间的差值
    isEnough := deadline.Sub(time.Now()) > time.Second * 5
    if isEnough {
        fmt.Println("copy file")
    } else {
        fmt.Println("isEnough is false return")
        return
    }
}

Beispiel für kontextgesteuerten Parallelitätscode. Bitte beachten Sie, dass die Ausführungsreihenfolge von Coroutinen zufällig ist. Aber Waitgroup ist eine Parallelitätskontrolle, die eine sequentielle Ausführung gewährleisten kann.

package main

import (
    "context"
    "fmt"
    "math/rand"
    "net/http"
    "os"
    "time"
)

func main(){
//context控制并发  WithCancel  cancel()
    ctx,cancel := context.WithCancel(context.Background())
   go Worker(ctx,"01")
   go Worker(ctx,"02")
   go Worker(ctx,"03")
    time.Sleep(time.Second * 5)
    fmt.Println("stop all")
    cancel()
    time.Sleep(time.Second * 1)
}

func Worker(ctx context.Context,name string ) {
    for {
        select{
        case <- ctx.Done():
            fmt.Println(name," stop the goroutine!")
            return
        default:
            fmt.Println(name," ing")
            time.Sleep(time.Second *1)
        }
    }
}

//结果打印:
//01  ing
//02  ing
//02  ing
//03  ing
//01  ing
//01  ing
//02  ing
//03  ing
//02  ing
//01  ing
//03  ing
//01  ing
//02  ing
//03  ing
//stop all
//02  stop the goroutine!
//03  stop the goroutine!
//01  stop the goroutine!

func main(){
// waitgroup来控制并发
    wg := sync.WaitGroup{}
    wg.Add(2)
    go func(){
        fmt.Println("1 job")
        wg.Done()
    }()
    go func(){
        fmt.Println(" 2 job")
        wg.Done()
    }()
    wg.Wait()
    fmt.Println(" end")
}

Abschließende Zusammenfassung:

1. Wertübertragung. --Wertübertragung ist nur eine Hilfsfunktion des Kontexts, die häufig verwendet wird: Cookies, Interceptoren oder Protokollinformationen, Debugging-Informationsdatensätze

2. Timeout-Kontrolle – HTTP-Einstellung Timeout, RPC-Aufruf – zeitaufwändige Vorgänge wie Datei-IO oder Netzwerk-IO können prüfen, ob die verbleibende Zeit ausreicht, und entscheiden, ob mit dem nächsten Schritt fortgefahren werden soll.

3. Steuerung abbrechen – Senden Sie ein Abbruchsignal, um sicherzustellen, dass alle von Ihrer eigenen Logik ausgehenden Goroutinen erfolgreich abgebrochen werden

Supongo que te gusta

Origin blog.csdn.net/xia_2017/article/details/128821215
Recomendado
Clasificación