Golang编程语言示例解析:ch1/dup2控制台与文件行为对比

Golang编程语言示例解析:ch1/dup2控制台与文件行为对比 大家好,

我是Go语言的新手,正在学习《Go程序设计语言》这本书,第一章的示例程序dup2。我创建了一个测试文件test.txt,内容如下:

harry
ron
hermione
ron
hagrid
dumbledore
harry
sneep
hermione

运行main.exe test.txt得到了预期的输出:

2       harry
2       ron
2       hermione

但是运行main.exe,通过键盘输入上述内容并以ctrl+c结束时,通常会漏掉一个条目(多次运行时漏掉的条目不一致)。可能的输出:

2       ron
2       hermione

或者

2       harry
2       ron

这是预期的行为吗?(我在Windows 10系统上运行,安装了go1.11.4版本。)

感谢帮助。


更多关于Golang编程语言示例解析:ch1/dup2控制台与文件行为对比的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

你好,能给我们看看这个程序吗?

更多关于Golang编程语言示例解析:ch1/dup2控制台与文件行为对比的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


《Go程序设计语言》的第一章可在线获取:http://www.gopl.io/ch1.pdf

dup2的代码印在第10页及后续页面。

你好Norbert,

这个:

NobbZ: 据我所知,Windows系统中相当于<kbd>Ctrl</kbd>-<kbd>D</kbd>的组合键是<kbd>Ctrl</kbd>-<kbd>Z</kbd>。

回答了我的问题,谢谢!

就我个人而言,如果运行这本书中链接的程序并使用<kbd>Ctrl</kbd>-<kbd>C</kbd>终止,我完全看不到任何后续输出。程序直接被取消,说实话,我认为在Windows系统上也会出现同样的情况。

但如果使用<kbd>Ctrl</kbd>-<kbd>D</kbd>(在Linux系统中用于发送EOF),每次都能看到正确的输出。

根据我的记忆,Windows系统中与<kbd>Ctrl</kbd>-<kbd>D</kbd>等效的操作是<kbd>Ctrl</kbd>-<kbd>Z</kbd>。

在Go语言中,dup2示例程序的行为差异是预期的,主要源于控制台输入和文件输入的处理方式不同。当从文件读取时,程序可以完整扫描整个内容;而从控制台输入时,依赖用户手动结束输入(如按Ctrl+C),这可能导致缓冲数据未完全处理。

以下是dup2的典型实现代码,基于《Go程序设计语言》第一章:

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    counts := make(map[string]int)
    files := os.Args[1:]
    if len(files) == 0 {
        countLines(os.Stdin, counts)
    } else {
        for _, arg := range files {
            f, err := os.Open(arg)
            if err != nil {
                fmt.Fprintf(os.Stderr, "dup2: %v\n", err)
                continue
            }
            countLines(f, counts)
            f.Close()
        }
    }
    for line, n := range counts {
        if n > 1 {
            fmt.Printf("%d\t%s\n", n, line)
        }
    }
}

func countLines(f *os.File, counts map[string]int) {
    input := bufio.NewScanner(f)
    for input.Scan() {
        counts[input.Text()]++
    }
    // 注意:忽略input.Err()可能的错误
}

行为分析:

  • 文件输入:程序读取整个文件,所有行被完整计数,输出所有重复行(如harryronhermione各出现2次)。
  • 控制台输入:当通过键盘输入并以Ctrl+C结束时,这是一个中断信号(SIGINT)。在Windows系统中,这可能导致缓冲的输入数据未被bufio.Scanner完全读取,因为扫描器可能在中断时尚未处理最后一行。例如,如果输入序列是:
    harry
    ron
    hermione
    ron
    [Ctrl+C]
    
    扫描器可能只捕获到部分行,取决于中断时机,从而漏掉harryhermione

示例重现控制台问题: 在控制台运行程序并输入:

harry
ron
hermione
ron
hagrid
dumbledore
harry
sneep
hermione
[Ctrl+C]

输出可能缺少一个条目,因为Ctrl+C立即终止进程,缓冲中的数据可能丢失。

总结: 这是预期行为,与控制台输入缓冲和中断处理相关。在类Unix系统(如Linux或macOS)上,行为可能类似,但Windows的终端处理略有差异。建议使用文件输入进行可靠测试,或通过标准输入重定向(如main.exe < test.txt)来模拟文件输入。

回到顶部