2017-01-12 5 views
5

starten Ich habe den folgenden Beispielcode. Ich möchte 4 Gokutinen laufen lassen. Sie haben die Möglichkeit, in Panik zu geraten. Im Falle der Panik habe ich eine Wiederherstellung, bei der ich die Goroutine neu starte.Golang, richtiger Weg, um eine Routine, die in Panik geraten

Die Art, wie ich implementiert, funktioniert, aber ich bin mir nicht sicher, ob es der richtige und richtige Weg ist, dies zu tun. Irgendwelche Gedanken

package main 

import (
    "fmt" 
    "time" 
) 

var gVar string 
var pCount int 

func pinger(c chan int) { 
    for i := 0; ; i++ { 
     fmt.Println("adding ", i) 
     c <- i 
    } 
} 

func printer(id int, c chan int) { 
    defer func() { 
     if err := recover(); err != nil { 
      fmt.Println("HERE", id) 
      fmt.Println(err) 
      pCount++ 
      if pCount == 5 { 
       panic("TOO MANY PANICS") 
      } else { 
       go printer(id, c) 
      } 
     } 
    }() 

    for { 
     msg := <-c 
     fmt.Println(id, "- ping", msg, gVar) 
     if msg%5 == 0 { 
      panic("PANIC") 
     } 

     time.Sleep(time.Second * 1) 

    } 
} 

func main() { 
    var c chan int = make(chan int, 2) 
    gVar = "Preflight" 
    pCount = 0 

    go pinger(c) 
    go printer(1, c) 
    go printer(2, c) 
    go printer(3, c) 
    go printer(4, c) 

    var input string 
    fmt.Scanln(&input) 
} 

Antwort

1

Oh, ich sage nicht, dass das folgende richtiger als dein Weg ist. Es ist nur ein anderer Weg, es zu tun.

Erstellen Sie eine andere Funktion, rufen Sie printerRecover oder so ähnlich, und tun Sie Ihre Verzögerung/Wiederherstellung dort. Dann in printer nur Schleife auf Anruf printerRecover. Fügen Sie Funktionsrückgabewerte hinzu, um zu prüfen, ob Sie die Goroutine aus irgendeinem Grund beenden müssen.

1

Wie Zan Lynx Antwort, ich würde gerne eine andere Möglichkeit teilen, es zu tun (obwohl es so ziemlich OP ähnelt.) Ich habe einen zusätzlichen gepufferten Kanal ch. Wenn eine goroutine in Panik gerät, sendet die Wiederherstellungsfunktion innerhalb der goroutine ihre Identität i an ch. In der for-Schleife am Ende von main() erkennt es, welche goroutine in Panik ist und ob sie neu startet, indem sie Werte von ch empfängt.

Run in Go Playground

package main 

import (
    "fmt" 
    "time" 
) 

func main() { 
    var pCount int 
    ch := make(chan int, 5) 

    f := func(i int) { 
     defer func() { 
      if err := recover(); err != nil { 
       ch <- i 
      } 
     }() 

     fmt.Printf("goroutine f(%v) started\n", i) 
     time.Sleep(1000 * time.Millisecond) 
     panic("goroutine in panic") 
    } 

    go f(1) 
    go f(2) 
    go f(3) 
    go f(4) 

    for { 
     i := <-ch 
     pCount++ 
     if pCount >= 5 { 
      fmt.Println("Too many panics") 
      break 
     } 
     fmt.Printf("Detected goroutine f(%v) panic, will restart\n", i) 
     f(i) 
    } 
} 
3

Sie können die Logik in einer Funktion wie erholen extrahieren:

func recoverer(maxPanics, id int, f func()) { 
    defer func() { 
     if err := recover(); err != nil { 
      fmt.Println("HERE", id) 
      fmt.Println(err) 
      if maxPanics == 0 { 
       panic("TOO MANY PANICS") 
      } else { 
       go recoverer(maxPanics-1, id, f) 
      } 
     } 
    }() 
    f() 
} 

Und es dann gerne verwenden:

go recoverer(5, 1, func() { printer(1, c) }) 
0

Die Art und Weise korrekt implementiert ist . Nur für mich sieht der Ansatz, um genau 4 routinemäßig laufen zu halten, nicht viel aus, entweder die routinemäßige ID handhabend, entweder in Verzögerung bringend, die unvorhersehbaren Stapel wegen der Schließung führen kann. Ich denke nicht, dass Sie auf diese Weise Ressourcen effizient ausgleichen können. Warum gehst du nicht wie einfache Laich Arbeiter, wenn es

benötigt
func main() { 
... 
    go func(tasks chan int){ //multiplexer 
     for { 
      task = <-tasks //when needed 
      go printer(task) //just spawns handler 
     } 
    }(ch) 
... 
} 

und lassen Laufzeit ihre Arbeit tun? Auf diese Weise werden Dinge in stdlib-Listenern/-Servern gemacht und sie sind als effizient genug bekannt. Göroutinen sind sehr leicht zu spawnen und die Laufzeit ist ziemlich intelligent, um die Last auszugleichen. Sicher, du musst dich auf jeden Fall erholen. Es ist meine sehr persönliche Meinung.

+0

Ich habe diese Methode versucht und es fügt einfach hinzu und fügt hinzu. Wie schränkt man die Anzahl der Goroutines ein? Es laicht Goroutines, die das Hauptproblem ist – Sakib

+0

@Sakib können Sie so etwas tun func main() { ... für i: = 0; ich

Verwandte Themen