Sie haben keine Systemressourcen mehr, weil Sie zu viele Dateideskriptoren verwenden, ohne genügend zu veröffentlichen. Sie müssen die Nebenläufigkeit in Ihrem Programm einschränken.
Dazu können Sie einen gepufferten Kanal haben, der als Zähl-Semaphor fungiert.
sem := make(chan struct{}, 12) // 12 is the maximum number of
// concurrent processes that may run at any time
Jetzt können Sie Ihre Methode ändern, wie:
func main() {
var wg sync.WaitGroup
wg.Add(1024 * 1024)
for i := 0; i < (1024 * 1024); i++ {
go func(index int) {
// if there are already 12 goroutines running, below send will block
// and a new file wont be open
sem <- struct{}{}
// once this goroutine finishes, empty the buffer by one
// so the next process may start (another goroutine blocked on
// above send will now be able to execute the statement and continue)
defer func() { <-sem }()
// wg.Done must be deferred after a read from sem so that
// it executes before the above read
defer wg.Done()
if f, e := os.Open(strconv.Itoa(index)); e != nil {
// handle file open failure
return
}
defer f.Close()
// handle open file
}(i)
}
wg.Wait()
close(sem)
}
Ihre Nutzung von wg.Done
auch falsch ist. Lesen Sie mehr über sie here
(Beachten Sie, dass dieser Code eine grundlegende Vorstellung über diese Art von Problem geben Sie auch auf diese Frage für ein Arbeitsbeispiel beziehen. Go worker pool with repetitive queue structure
die Antwort nicht verwandt ist gehen, aber lesen Die Manpage für "ulimit". Allerdings - a. Sie Code hat zwei katastrophale Bugs, sehen Sie, ob Sie sie erkennen. Und b. Darüber hinaus versuchen Sie, 1M Dateien auf einmal zu öffnen, es sei denn, Sie haben eine massive RAID Array ist das nicht praktikabel –
Was ist Ihr Betriebssystem, ist es Unix/Linux? – kopiczko
ulimit ist nicht die beste Lösung. Ich würde lieber nur eine begrenzte Anzahl von goroutines haben, die Dateien öffnen und verarbeiten (vielleicht 500 parallel geöffnete Dateien) Und jede Goroutine sollte Eingaben von demselben Kanal auswählen, öffnet t er Datei, lesen und schließen Sie es, und schickte das Ergebnis zurück zu anderen Kanal. Dieser zweite Kanal sollte Teil der Anfrage sein. Und jeder, der diese Goroutine benutzen soll, sollte diesen Kanal erstellen, eine Anfrage senden und auf das Ergebnis warten. Verstehst du, oder du brauchst ein Beispiel? – lofcek