如何在不使用频道阻塞的情况下使用代码报告统计信息?
How to report stats with ticker without blocking using channel?
我想在读取大文件时每 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()
}
默认使用select以避免在自动收报机上阻塞。从自动收报机接收到值时记录:
select {
case <-ticker.C:
percent := ( float64(sourceReadedBytes) * float64(100) ) / float64(sourceTotalSizeBytes)
og.Printf("%v / %v %v%%", sourceReadedBytes, sourceTotalSizeBytes, percent)
default:
// do nothing
}
我想在读取大文件时每 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()
}
默认使用select以避免在自动收报机上阻塞。从自动收报机接收到值时记录:
select {
case <-ticker.C:
percent := ( float64(sourceReadedBytes) * float64(100) ) / float64(sourceTotalSizeBytes)
og.Printf("%v / %v %v%%", sourceReadedBytes, sourceTotalSizeBytes, percent)
default:
// do nothing
}