os.open竟然在文件不存在时返回err==nil,亏我那么信任它

jan-bar · 2019-09-15 11:47:05 · 3714 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2019-09-15 11:47:05 的主题,其中的信息可能已经有所发展或是发生改变。

package main

import (
    "fmt"
    "os"
)

func main() {
    f := "D:\\cron"
    fmt.Println(os.Stat(f))
    fmt.Println(os.Open(f))

    f = "D:\\con"
    fmt.Println(os.Stat(f))
    fmt.Println(os.Open(f))
}

结果如下:
<nil> CreateFile D:\cron: The system cannot find the file specified.
<nil> open D:\cron: The system cannot find the file specified.
<nil> CreateFile D:\con: The parameter is incorrect.
&{0xc000086a00} <nil>

我就是想读取一个文件,我觉得os.Open()应该在文件不存在时返回错误,这样我就可以不多调一次os.Stat()
然而不知为啥会碰到上面这个问,搞不懂“D:\con”这个为啥会是参数错误,而且os.Open竟然返回正常。


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3714 次点击  
加入收藏 微博
26 回复  |  直到 2022-01-05 20:28:24
focusonline
focusonline · #1 · 6年之前

这就尴尬了,要么楼主给Go团队提一个bug?

tangname
tangname · #2 · 6年之前

😂 有空自己试试

jan-bar
jan-bar · #3 · 6年之前

问题找到了,可以百度“Windows中不能用con等作为文件名”,我这是碰巧踩了一个大大的坑。

jan-bar
jan-bar · #4 · 6年之前

到stackoverflow几分钟出答案,可以百度“Windows中不能用con等作为文件名”,我这是碰巧踩了一个大大的坑。

ryanyntc
ryanyntc · #5 · 6年之前

如果你打开文件的目的是写文件应不应该报错呢?

jan-bar
jan-bar · #6 · 6年之前

5楼 @ryanyntc

func Open(name string) (*File, error) {
    return OpenFile(name, O_RDONLY, 0)
}

这是go源码,只读方式打开没法写吧。

jan-bar
jan-bar · #7 · 6年之前

我已经放到stackoverflow上求有缘人解释解释点击链接
放到stackoverflow不到几分钟就有答案了,简直可以超神了啊。
可以百度“Windows中不能用con等作为文件名”,我这是碰巧踩了一个大大的坑。

polaris
polaris · #8 · 6年之前

没有 windows 环境,没法试。我本地是没问题

jan-bar
jan-bar · #9 · 6年之前
polarispolaris #8 回复

没有 windows 环境,没法试。我本地是没问题

stackoverflow上不到几分钟就有答案点击链接
可以百度“Windows中不能用con等作为文件名”,我这是碰巧踩了一个大大的坑。

polaris
polaris · #10 · 6年之前

这坑,真是可以

jan-bar
jan-bar · #11 · 6年之前
ryanyntcryanyntc #5 回复

如果你打开文件的目的是写文件应不应该报错呢?

问题找到了,可以百度“Windows中不能用con等作为文件名”,我这是碰巧踩了一个大大的坑。

jan-bar
jan-bar · #12 · 6年之前
polarispolaris #10 回复

这坑,真是可以

确实,我无意间踩坑,踩的不知所措,苦笑。

tangname
tangname · #13 · 6年之前

@jan-bar 学到了。这种坑可以提交issue.

archxm
archxm · #14 · 5年之前

遇到这个问题的时候,谁tmd会想到这么个坑

anko
anko · #15 · 5年之前

image.png open()方法返回2个值,第一个是file,第二个才是错误信息,如果出现错误,第一个值为nil太正常不过了吧? 总结:不关你的文件名是什么的事!

jan-bar
jan-bar · #16 · 5年之前
ankoanko #15 回复

![image.png](https://static.studygolang.com/191017/eb71a34727524ebf7f79932fd85e5dce.png) open()方法返回2个值,第一个是file,第二个才是错误信息,如果出现错误,第一个值为nil太正常不过了吧? 总结:不关你的文件名是什么的事!

我的意思是打开f = "D:\con"这个文件为什么没有报错?得到的第一个返回值不是nil,请问此时这第一个参数能按照预期使用么?

TryHenry
TryHenry · #17 · 5年之前

学到了学到了。

anko
anko · #18 · 5年之前
jan-barjan-bar #16 回复

#15楼 @anko 我的意思是打开f = "D:\\con"这个文件为什么没有报错?得到的第一个返回值不是nil,请问此时这第一个参数能按照预期使用么?

第一个返回值的值是nil,难道你还能read()?我没试过,应该可以read,然后read也是读不到什么的!类型肯定还是*File类型,同样也可以调用这个对象下面的方法,但是读取不到任何东西。因为read()方法会进行检查的!如果你传递过的参数是一个nil值,那么肯定不会进行读取了,而是直接抛出“无效参数”的错误!如下:
image.png

anko
anko · #19 · 5年之前
jan-barjan-bar #16 回复

#15楼 @anko 我的意思是打开f = "D:\\con"这个文件为什么没有报错?得到的第一个返回值不是nil,请问此时这第一个参数能按照预期使用么?

我明白你的意思了,我自己试了下确实是不可以使用con这个东西,会出现bug: image.png

Naux
Naux · #20 · 3年之前

image.png 感觉con这东西是特殊的, 我用C和go 都试过, 结果是一样的,con确实存在问题。 不清楚windows系统D:\con 历史上,是不是把这个路径作为特殊设备描述符来着, 比如光驱。

jan-bar
jan-bar · #21 · 3年之前
NauxNaux #20 回复

![image.png](https://static.studygolang.com/211110/6b55217ffd6f35b4dda5f8072f864893.png) 感觉con这东西是特殊的, 我用C和go 都试过, 结果是一样的,con确实存在问题。 不清楚windows系统D:\con 历史上,是不是把这个路径作为特殊设备描述符来着, 比如光驱。

隔了这么久没想到还有人看这篇帖子。。我就把go源码发上来吧,这是后面阅读源码发现的额。

image.png

Naux
Naux · #22 · 3年之前
jan-barjan-bar #21 回复

#20楼 @Naux 隔了这么久没想到还有人看这篇帖子。。我就把go源码发上来吧,这是后面阅读源码发现的额。 ![image.png](https://static.studygolang.com/211112/d3d52266809e4108a30f191f4e377747.png)

嗯, 好的, 学到了

yincyu
yincyu · #23 · 3年之前

1.17 显示找不到的错误,不知道是不是修复了。

jan-bar
jan-bar · #24 · 3年之前
yincyuyincyu #23 回复

1.17 显示找不到的错误,不知道是不是修复了。

不对啊。。我试了1.17的os.Open("D:\\con"),err返回的还是nil,这个算是一个注意点吧。

hjlh99
hjlh99 · #25 · 3年之前

路过,学了一招

yincyu
yincyu · #26 · 3年之前

@jan-bar 我意思是这个修复了, 我报错是没有这个目录, 正常的报错,不是楼主的参数不正确, 有这个目录就不会有错误。

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传