2017-11-11 9 views
2

大きなファイルを読みながらN秒ごとにさまざまな統計を報告したいと思います。私はティッカーとチャンネルを見つけましたが、バックグラウンドでファイルを読み続けている間に非ブロックにする方法を見つけられません。私はまた、文字列チャネルを作成しようとしましたselect{ case: <-msg}しかし、プログラムがデッドロックにクラッシュします。適切な方法は何ですか?ティッカーを使用してチャネルを使用してブロックすることなく統計情報を報告するにはどうすればよいですか?

後で、必要な速度と時間を定期レポートに含めることができるように、差分を追加することにします。

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() 
} 

答えて

2

デフォルトでselectを使用すると、ティッカーがブロックされません。ティッカーから値を受け取ったときのログ:

select { 
case <-ticker.C: 
    percent := (float64(sourceReadedBytes) * float64(100))/float64(sourceTotalSizeBytes) 
    og.Printf("%v/%v %v%%", sourceReadedBytes, sourceTotalSizeBytes, percent) 
default: 
    // do nothing 
} 
関連する問題