我是Go的新手,我想做一个简单的程序,从用户读取文件名并将其内容显示给用户。这就是我到目前为止所做的:
fname := "D:\myfolder\file.txt"
f, err := os.Open(fname)
if err != nil {
fmt.Println(err)
}
var buff []byte
defer f.Close()
buff = make([]byte, 1024)
for {
n, err := f.Read(buff)
if n > 0 {
fmt.Println(string(buff[:n]))
}
if err == io.EOF {
break
}
}
但我收到错误:
文件名,目录名或卷标语法不正确。
答案 0 :(得分:2)
我怀疑fname
中的反斜杠是原因。尝试使用双反斜杠(\\
)。
答案 1 :(得分:2)
将文件名放在反引号中。这使它成为原始字符串文字。使用原始字符串文字时,不会处理\f
之类的转义序列。
fname := `D:\myfolder\file.txt`
答案 2 :(得分:0)
你也可以使用unix' /'而是路径分隔符。 这份工作。
fname := "D:/myfolder/file.txt"
答案 3 :(得分:0)
恭喜学习Go!虽然问题是关于示例中的特定错误,但是让我们逐行分解并了解一些可能遇到的其他问题:
fname := "D:\myfolder\file.txt"
与C和许多其他语言一样,Go使用反斜杠字符表示"转义序列"。也就是说,以反斜杠开头的某些字符会被翻译成其他难以看到的字符(例如。\t
成为制表符,否则可能与空格无法区分)。
修复是使用原始字符串文字(使用反引号而不是引号),其中没有处理转义序列:
fname := `D:\myfolder\file.txt`
这可以通过删除无效的\m
和\f
转义序列来修复您看到的初始错误。通过阅读Go规范的String Literals部分,可以找到完整的转义序列列表和更多解释。
f, err := os.Open(fname)
if err != nil {
fmt.Println(err)
}
这个块的第一行很好,但可以改进。如果发生错误,我们的程序没有理由继续执行,因为我们甚至无法打开文件,因此我们应该打印它(可能是标准错误)并退出,最好是非零退出状态表明发生了一些不好的事情。另外,作为一个好习惯,我们可能希望在函数结束时关闭文件,如果打开它成功的话。将它放在Open调用的正下方是常规的,当其他人正在阅读您的代码时会更容易。我会把它重写为:
f, err := os.Open(fname)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
// It is also common to replace these two lines with a call to log.Fatal
}
defer f.Close()
最后一个块有点复杂,我们可以用多种方式重写它。现在它看起来像这样:
var buff []byte
defer f.Close()
buff = make([]byte, 1024)
for {
n, err := f.Read(buff)
if n > 0 {
fmt.Println(string(buff[:n]))
}
if err == io.EOF {
break
}
}
但我们不需要定义自己的缓冲,因为标准库为我们提供了bufio
和bytes
个包,它们可以为我们做到这一点。在这种情况下,我们可能不需要它们,因为我们也可以通过调用io.Copy
替换迭代,io.CopyBuffer
执行自己的内部缓冲。如果我们想使用自己的缓冲区,我们也可以使用其他副本变体,如{{3}}。它也缺少一些错误处理,所以我们将添加它。现在整个块变成了:
_, err := io.Copy(os.Stdout, f)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading from file: `%s'\n", err)
os.Exit(2)
}
// We're done!