如何使用通道报告带有自动收报机的统计数据?

时间:2017-11-11 23:36:40

标签: go nonblocking

我想在读取大文件时每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()
}

1 个答案:

答案 0 :(得分:2)

使用默认值选择以避免在代码上阻止。从代码收到值时记录:

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