2017-11-11 9 views
2

Ich möchte verschiedene Statistiken alle N Sekunden beim Lesen großer Datei berichten. Ich habe den Ticker und die Kanäle gefunden, kann aber nicht herausfinden, wie man das Blockieren verhindert und gleichzeitig die Datei im Hintergrund liest. Ich habe auch versucht, String-Kanal und verwenden Sie select{ case: <-msg}, aber das Programm stürzt dann auf Deadlock. Was ist der richtige Weg?Wie kann man Statistiken mit einem Ticker melden, ohne den Kanal zu blockieren?

Später werde ich wahrscheinlich Diffs hinzufügen, so dass die Geschwindigkeit und die benötigte Zeit auch im periodischen Bericht enthalten sein können.

package main 

import (
    "log" 
    "os" 
    "fmt" 
    "bufio" 
    "strings" 
    "time" 
) 

func main() { 
    filename := "large-file.dat" 

    log.Printf("Opening file: '%v'", filename) 
    file, err := os.Open(filename) 
    if err != nil { 
     fmt.Fprintf(os.Stderr, "File error: %v", err) 
     os.Exit(1) 
    } 

    sourceTotalSizeBytes := uint64(0) 
    sourceReadedBytes := uint64(0) 

    if finfo, err := file.Stat(); err == nil { 
     sourceTotalSizeBytes = uint64(finfo.Size()) 
     log.Printf("Size: %v bytes", sourceTotalSizeBytes) 
    } 

    scanner := bufio.NewScanner(file) 

    // Output stats every n seconds 
    ticker := time.NewTicker(time.Second * 2) 
    defer ticker.Stop() 

    for scanner.Scan() { 
     lineReader := strings.NewReader(scanner.Text()) 
     sourceReadedBytes += uint64(lineReader.Size()) 

     // Report stats every n seconds 
     <-ticker.C 
     go func() { 
      percent := (float64(sourceReadedBytes) * float64(100))/float64(sourceTotalSizeBytes) 
      log.Printf("%v/%v %v%%", sourceReadedBytes, sourceTotalSizeBytes, percent) 
     }() 

     // Simulate work being done to line 
     time.Sleep(time.Millisecond * 10) 

    } 

    file.Close() 
} 

Antwort

2

Verwenden Sie die Option standardmäßig auswählen, um eine Blockierung auf dem Ticker zu vermeiden. Protokollieren, wenn ein Wert vom Ticker empfangen wird:

select { 
case <-ticker.C: 
    percent := (float64(sourceReadedBytes) * float64(100))/float64(sourceTotalSizeBytes) 
    og.Printf("%v/%v %v%%", sourceReadedBytes, sourceTotalSizeBytes, percent) 
default: 
    // do nothing 
} 
Verwandte Themen