Golang Go语言中可能出现文件打开但是报错的情况吗

发布于 1周前 作者 gougou168 来自 Go语言

正常打开文件的模式代码就是这样,我想问下各位大佬可能出现 err 不为空但是文件被打开的情况吗

file, err := os.Open(“filename.txt”)
if err != nil {
// 处理错误
}
defer file.Close()

因为我想的是可能这么写更好些?

file, err := os.Open(“filename.txt”)
defer file.Close() // defer 写在 err 前面
if err != nil {
// 处理错误
}
Golang Go语言中可能出现文件打开但是报错的情况吗


更多关于Golang Go语言中可能出现文件打开但是报错的情况吗的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

28 回复

defer 是在 return 前才调用

更多关于Golang Go语言中可能出现文件打开但是报错的情况吗的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


但是一般 error 里面就返回了

出错了也就不用再去关闭句柄了,所以一般是先判断 err 吧

第一个 os.Open 如果返回了 err ,那么 file 必定是 nil ,这种情况下不需要 Close 。只有 err == nil 的情况下,才需要在最结尾 close 。
当然如果按你下面的写法也没错,实际上 file.Close 当 file==nil 的时候,会返回一个 ErrInvalid ,这个你看一下 go 的源码就清楚了。

gpt 答案:
在 Go 语言中,如果在尝试打开文件时返回的 err 不为 nil ,那么这意味着在打开文件的过程中出现了一些错误。在这种情况下,file 变量通常会是 nil ,所以你无法或者不需要调用 file.Close()。

全文:
https://chat.openai.com/share/bb186187-feb5-4970-b36f-6c0914f6e668

看下源码 不就知道了,正常的接口设计不会出现你说的情况

所以我多想了一下,是 golang 都有这个标准,出现 err 就不需要管别的返回了,还是说 err 存在但是 file 也打开了的情况

源码是写的 nil ,但是可不可能在系统层面还是打开的,也就是文件里面的引用指针还是+1 了的情况,这块研究不深,所以想问问大佬们

我能理解,毕竟这个底层也是 golang 官方库,只是好奇的想确认下文件这块的操作流程是不是符合预期

这么想了下也确实

Close 的代码你看一下就懂了,返回为 nil 的时候根本就没涉及到资源处理。
func (f *File) Close() error {
if f == nil {
return ErrInvalid
}
return f.file.close()
}


Open 的代码:
func OpenFile(name string, flag int, perm FileMode) (*File, error) {
testlog.Open(name)
f, err := openFileNolog(name, flag, perm)
if err != nil {
return nil, err
}
f.appendMode = flag&O_APPEND != 0

return f, nil
}

要么 f 有值,err==nil ,要么 f==nil ,err 有值。只有这两种可能。而 err 有值的情况下,f==nil 也是不用 close 的。

好像懂了。也就是 golang 这块 我只要做到正常的处理就行了,底层它内部调用的文件系统是否关闭了文件,我这边也处理不到了。原本是想了解下这个底层是否关闭了,影不影响上层处理。,从写 golang 逻辑下,正常写法就已经是完美了。

#8 既然用 go 的库,那么“如果 Open 返回的 err 不为 nil ,而实际系统层面文件是打开的”这件事情应该是 go 需要考虑的,甚至(如果真是这样的话)算是一个 bug 。

先别想这些细节上的优化,先把代码跑起来,遇到了再说。

确实是这样。至少代码层面开发者能做的都做到了。

代码就在面前,为什么不点进去看一下呢

你只要记住 golang 的 convention 是,调用一个会返回错误的函数时,只在检查完错误之后才能使用其他返回值。没有检查错误或错误不为 nil 时其他返回值都可以认为是无效的,使用此值可以看作 undefined behavior 。
这主要是因为 go 欠缺 union type 。

我可能想的太多了,纯粹好奇问一下

这个是的,确实能理解了

#16

没记错的话,io.EOF 是个例外。。

不过它不在 Open 而在 Read 用。

这个我当然知道,所以说这是 convention ,convention 有例外是很正常的。
像这种情况在其他类型严格且表达能力足够的语言中,接口可以返回一个专门的 IOResult ,与普通的 Result 区分。

约定俗成,标准库里直接可以认为这俩互斥,但没有类型系统保证,第三方库保险起见看看实现就好了

golang 提供的官方标准库里,出现了你设想的那种场景,那就是 bug ,golang 官方负责解决,你下层不用想能解决上层的问题。

你引用了的别人的三方库里出现这种问题,那是哪个库作者的 bug ,库作者负责解决这种问题,你下层不用想能解决上层的问题。

确实是这个道理

os.Open Go 源码如下:
func Open(name string) (*File, error) {
return OpenFile(name, O_RDONLY, 0)
}

func OpenFile(name string, flag int, perm FileMode) (*File, error) {
testlog.Open(name)
f, err := openFileNolog(name, flag, perm)
if err != nil {
return nil, err
}
f.appendMode = flag&O_APPEND != 0

return f, nil
}

从这里可以看到,如果 open file 的时候,出现了 error ,os.Open 返回的第一个值是 nil, 那么此时也就不需要再进行 close

在Golang(Go语言)中,确实可能出现文件打开但随后报错的情况。这通常发生在文件打开后的各种操作中,而不仅仅是打开动作本身。以下是一些可能导致这种情况的常见原因及处理方式:

  1. 文件权限问题:即使文件成功打开,如果在后续操作中尝试进行读写等权限受限的操作,也会报错。确保文件权限与操作相匹配。

  2. 文件路径或句柄错误:有时文件句柄可能在后续操作中因错误使用而失效,或者文件路径在运行时发生变化导致无法找到文件。检查文件路径和句柄的使用是否正确。

  3. 磁盘或文件系统错误:磁盘故障、文件系统损坏或达到存储限制也可能导致文件操作失败。监控磁盘状态和文件系统健康。

  4. 并发访问冲突:在多线程或多进程环境中,如果多个线程/进程同时尝试对同一文件进行不兼容的操作(如一个读一个写),可能会引发错误。使用锁机制或其他同步方法管理并发访问。

  5. 资源限制:系统资源限制(如打开文件描述符的数量)也可能导致文件操作失败。检查并调整系统资源限制。

在编写Go代码时,建议对文件操作进行错误检查,并使用defer语句确保文件在不再需要时被正确关闭,以减少资源泄露和潜在错误。同时,使用适当的错误处理策略(如重试机制、错误日志记录等)来提高程序的健壮性。

回到顶部