Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File &引用;尾部-f“-类似发电机_File_Go_Generator - Fatal编程技术网

File &引用;尾部-f“-类似发电机

File &引用;尾部-f“-类似发电机,file,go,generator,File,Go,Generator,我在Python中有一个方便的函数: def follow(path): with open(self.path) as lines: lines.seek(0, 2) # seek to EOF while True: line = lines.readline() if not line: time.sleep(0.1) cont

我在Python中有一个方便的函数:

def follow(path):
    with open(self.path) as lines:
        lines.seek(0, 2)  # seek to EOF

        while True:
            line = lines.readline()
            if not line:
                time.sleep(0.1)
                    continue
                yield line 
它的功能类似于UNIX
tail-f
:您可以在文件的最后一行出现时获取它们。这很方便,因为您可以在不阻塞的情况下获取生成器并将其传递给另一个函数

然后我不得不在围棋中做同样的事情。我不熟悉这门语言,所以我不确定我所做的是否足够地道/正确

代码如下:

func Follow(fileName string) chan string {

    out_chan := make(chan string)

    file, err := os.Open(fileName)
    if err != nil {
        log.Fatal(err)
    }

    file.Seek(0, os.SEEK_END)
    bf := bufio.NewReader(file)

    go func() {
        for {
            line, _, _ := bf.ReadLine()

            if len(line) == 0 {
                time.Sleep(10 * time.Millisecond)
            } else {
                out_chan <- string(line)
            }
        }

        defer file.Close()
        close(out_chan)
    }()

    return out_chan
}
func Follow(文件名字符串)chan字符串{
out_chan:=make(chan字符串)
文件,错误:=os.Open(文件名)
如果错误!=零{
log.Fatal(错误)
}
file.Seek(0,os.Seek_END)
bf:=bufio.NewReader(文件)
go func(){
为了{
行,,:=bf.ReadLine()
如果len(line)==0{
时间。睡眠(10*时间。毫秒)
}否则{

out_chan我建议为睡在EOF上的读者创建一个包装:

type tailReader struct {
    io.ReadCloser
}

func (t tailReader) Read(b []byte) (int, error) {
    for {
        n, err := t.ReadCloser.Read(b)
        if n > 0 {
            return n, nil
        } else if err != io.EOF {
            return n, err
        }
        time.Sleep(10 * time.Millisecond)
    }
}

func newTailReader(fileName string) (tailReader, error) {
    f, err := os.Open(fileName)
    if err != nil {
        return tailReader{}, err
    }

    if _, err := f.Seek(0, 2); err != nil {
        return tailReader{}, err
    }
    return tailReader{f}, nil
}
此读卡器可用于io的任何位置。读卡器可用于任何位置。以下是如何使用以下命令在线路上循环:

读取器还可用于循环附加到文件的JSON值:

t, err := newTailReader("somefile")
if err != nil {
    log.Fatal(err)
}
defer t.Close()
dec := json.NewDecoder(t)
for {
    var v SomeType
    if err := dec.Decode(&v); err != nil {
       log.Fatal(err)
    }
    fmt.Println("the value is ", v)
}
与问题中概述的goroutine方法相比,这种方法有几个优点。第一个优点是关闭很容易。只需关闭文件。无需向goroutine发出退出的信号。第二个优点是许多包与io.Reader一起工作


睡眠时间可以根据具体需要进行上下调整。减少延迟时间并增加时间以减少CPU使用。100毫秒的睡眠时间对于向人类显示的数据来说可能已经足够快了。

查看此Go软件包以读取持续更新的文件(tail-f):


使用
os.SEEK\u END
而不是
2
time.Sleep(10)
睡眠10纳秒,您可能指的是
time.Sleep(10*time.毫秒)
。一旦
io.Reader
给你
io.EOF
你不应该期望它会给你更多的数据;EOF==文件结束/steam,没有更多的数据。谢谢,我编辑了代码。我发现有两件事是错误的…[1]时间。睡眠(10*时间。毫秒)将导致系统产生热量,而不是静静地坐着,直到实际有一些数据。[2]当您在文件末尾时,主循环没有信号,因此您可以决定退出。(我有一个用例,我向服务发送一些命令;然后监视等待肯定答复的日志;因为没有否定答复,我需要耗尽数据或检查计时器。Goroutines和关闭数据源不是一个选项。@Richard(1)调整睡眠时间,以平衡延迟和电源。(2)如果您需要在某个截止日期之前耗尽数据,那么在睡觉之前修改答案中的代码以检查截止日期。
t, err := newTailReader("somefile")
if err != nil {
    log.Fatal(err)
}
defer t.Close()
dec := json.NewDecoder(t)
for {
    var v SomeType
    if err := dec.Decode(&v); err != nil {
       log.Fatal(err)
    }
    fmt.Println("the value is ", v)
}
t, err := tail.TailFile("filename", tail.Config{Follow: true})
for line := range t.Lines {
    fmt.Println(line.Text)
}