Heim  >  Artikel  >  Backend-Entwicklung  >  Golang kopiert alle Kontextwerte

Golang kopiert alle Kontextwerte

WBOY
WBOYnach vorne
2024-02-05 23:39:07828Durchsuche

Golang kopiert alle Kontextwerte

Frageninhalt

Ich habe eine HTTP-Serveranwendung, die asynchrone Jobs verarbeitet.

-> Request
   --> Do async job with goroutine
<- Response
    -------start goroutine------
       -> Job1
          -> Job1A
          -> Job1B
       -> Job2
       -> Job3

Benutzer können asynchrone Jobs mit langer Laufzeit anfordern und die Anwendung antwortet sofort nach make goroutine auf die Anfrage.

Ich habe die Anforderungs-ID, das authentifizierte Token und die Benutzerinformationen in die context.Context 中。而且,我想把它放在 goroutine 下。但是,对请求 context 使用相同的 context der Anforderung eingefügt, was zu einem unerwarteten Abbruch nach der Antwort führt, was nicht mein beabsichtigtes Verhalten ist.

Wie generiert man neue context,独立于父请求 context?或者,还有其他方法可以保证 context mit allen Werten, ohne zu sterben, nachdem man die Antwort von Goroutine eingebracht hat?

Und eine Bonusfrage:

Stornierung von

Job1 ~ Job3 应该被序列化,即 Job2 应该等待 Job1Job3 等待 Job2。并且,Job1AJob1B 可以同时运行。如果我想传播给定 context, wie kann ich ihren Pfad(?) stornieren? Sollte ich Select-Anweisungen für alle Funktionen überprüfen?

Ich verstehe, context das Konzept der Stornierung und des vorzeitigen Ausstiegs zu propagieren, ohne sinnlose Aufgaben zu erledigen. Allerdings habe ich nicht herausgefunden, wie ich damit im Code umgehen soll. Ich würde mich freuen, wenn mir jemand beim Verständnis helfen könnte.


Richtige Antwort


Der Wert im Kontext kann nicht ermittelt werden. Sie werden nicht als Karten, sondern als Kontextebenen gespeichert, wobei jede Ebene möglicherweise eine andere Implementierung der Speicherung von Werten bietet.

Wenn Sie jedoch wissen, welche Werte weitergegeben werden müssen, können Sie diese abfragen und mit diesen Werten einen neuen Kontext erstellen.

Das heißt, Sie können einen neuen Kontexttyp implementieren, der Werte aus einem anderen Kontext verwendet:

type newContext struct {
  context.Context
  values context.Context
}

func (c newContext) Value(key any) any {
  return c.values.Value(key)
}

...
newCtx:=newContext{
  Context: context.Background(),
  values: ctx,
}

Dabei wird der bestehende Wertekontext und ein neuer Kontext für alles andere genutzt.

Dann starten Sie eine neue Goroutine, um die Verarbeitung von Anfragen im neuen Kontext fortzusetzen.

Wenn Sie mehrere gleichzeitige Jobs erstellen möchten, können Sie dies in dieser Goroutine tun:

go func(ctx context.Context) {
   withCancel, cancel:=context.WithCancel(ctx)
   defer cancel()

   wg:=sync.WaitGroup{}
   wg.Add(2)
   go job1(withCancel,&wg)
   go job2(withCancel,&wg)
   wg.Wait()
}(newCtx)

Auf diese Weise erhalten beide Jobs eine Stornierungsbenachrichtigung, wenn der Kontext abgebrochen wird. Wenn Sie den Abbruch von Job1 und Job2 separat steuern möchten:

go func(ctx context.Context) {
   withCancel1, cancel1:=context.WithCancel(ctx)
   defer cancel1()
   withCancel2, cancel2:=context.WithCancel(ctx)
   defer cancel2()

   wg:=sync.WaitGroup{}
   wg.Add(2)
   go job1(withCancel1,&wg)
   go job2(withCancel2,&wg)
   wg.Wait()
}(newCtx)

Für aufeinanderfolgende Jobs (d. h. Job 3 endet nach Job 1) kombinieren Sie sie einfach so, dass sie wie ein einziger Job aussehen.

Um zu überprüfen, ob ein Kontext abgebrochen wurde, können Sie dies im Done 通道上执行 select ​​des Kontexts tun oder einfach Folgendes überprüfen:

if ctx.Err()!=nil {
   // Context canceled
}

Das obige ist der detaillierte Inhalt vonGolang kopiert alle Kontextwerte. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen