V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Assassinrx
V2EX  ›  Go 编程语言

golang 可能出现文件打开但是报错的情况吗

  •  1
     
  •   Assassinrx · 321 天前 · 1421 次点击
    这是一个创建于 321 天前的主题,其中的信息可能已经有所发展或是发生改变。
    正常打开文件的模式代码就是这样,我想问下各位大佬可能出现 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 {
    // 处理错误
    }
    27 条回复    2023-07-25 17:10:29 +08:00
    seers
        1
    seers  
       321 天前
    defer 是在 return 前才调用
    Assassinrx
        2
    Assassinrx  
    OP
       321 天前
    @seers 但是一般 error 里面就返回了
    R0n1n
        3
    R0n1n  
       321 天前
    出错了也就不用再去关闭句柄了,所以一般是先判断 err 吧
    zhs227
        4
    zhs227  
       321 天前
    第一个 os.Open 如果返回了 err ,那么 file 必定是 nil ,这种情况下不需要 Close 。只有 err == nil 的情况下,才需要在最结尾 close 。
    当然如果按你下面的写法也没错,实际上 file.Close 当 file==nil 的时候,会返回一个 ErrInvalid ,这个你看一下 go 的源码就清楚了。
    twistedmeadows
        5
    twistedmeadows  
       321 天前 via iPhone
    gpt 答案:
    在 Go 语言中,如果在尝试打开文件时返回的 err 不为 nil ,那么这意味着在打开文件的过程中出现了一些错误。在这种情况下,file 变量通常会是 nil ,所以你无法或者不需要调用 file.Close()。

    全文:
    https://chat.openai.com/share/bb186187-feb5-4970-b36f-6c0914f6e668
    lasuar
        6
    lasuar  
       321 天前
    看下源码 不就知道了,正常的接口设计不会出现你说的情况
    Assassinrx
        7
    Assassinrx  
    OP
       321 天前
    @R0n1n 所以我多想了一下,是 golang 都有这个标准,出现 err 就不需要管别的返回了,还是说 err 存在但是 file 也打开了的情况
    Assassinrx
        8
    Assassinrx  
    OP
       321 天前
    @zhs227 源码是写的 nil ,但是可不可能在系统层面还是打开的,也就是文件里面的引用指针还是+1 了的情况,这块研究不深,所以想问问大佬们
    Assassinrx
        9
    Assassinrx  
    OP
       321 天前
    @lasuar 我能理解,毕竟这个底层也是 golang 官方库,只是好奇的想确认下文件这块的操作流程是不是符合预期
    Assassinrx
        10
    Assassinrx  
    OP
       321 天前
    @twistedmeadows 这么想了下也确实
    zhs227
        11
    zhs227  
       321 天前
    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 的。
    aeof
        12
    aeof  
       321 天前 via Android
    不可能出现
    Assassinrx
        13
    Assassinrx  
    OP
       321 天前
    @zhs227 好像懂了。也就是 golang 这块 我只要做到正常的处理就行了,底层它内部调用的文件系统是否关闭了文件,我这边也处理不到了。原本是想了解下这个底层是否关闭了,影不影响上层处理。,从写 golang 逻辑下,正常写法就已经是完美了。
    Assassinrx
        14
    Assassinrx  
    OP
       321 天前
    @aeof 行!
    harrozze
        15
    harrozze  
       321 天前
    @Assassinrx #8 既然用 go 的库,那么“如果 Open 返回的 err 不为 nil ,而实际系统层面文件是打开的”这件事情应该是 go 需要考虑的,甚至(如果真是这样的话)算是一个 bug 。

    先别想这些细节上的优化,先把代码跑起来,遇到了再说。
    Assassinrx
        16
    Assassinrx  
    OP
       321 天前
    @harrozze 确实是这样。至少代码层面开发者能做的都做到了。
    admpubcom
        17
    admpubcom  
       321 天前 via iPhone
    代码就在面前,为什么不点进去看一下呢
    Jirajine
        18
    Jirajine  
       321 天前
    你只要记住 golang 的 convention 是,调用一个会返回错误的函数时,只在检查完错误之后才能使用其他返回值。没有检查错误或错误不为 nil 时其他返回值都可以认为是无效的,使用此值可以看作 undefined behavior 。
    这主要是因为 go 欠缺 union type 。
    Assassinrx
        19
    Assassinrx  
    OP
       321 天前
    @admpubcom 我可能想的太多了,纯粹好奇问一下
    Assassinrx
        20
    Assassinrx  
    OP
       321 天前
    @Jirajine 这个是的,确实能理解了
    flyqie
        21
    flyqie  
       321 天前 via Android
    @Jirajine #16

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

    不过它不在 Open 而在 Read 用。
    Jirajine
        22
    Jirajine  
       321 天前
    @flyqie 这个我当然知道,所以说这是 convention ,convention 有例外是很正常的。
    像这种情况在其他类型严格且表达能力足够的语言中,接口可以返回一个专门的 IOResult ,与普通的 Result 区分。
    timpaik
        23
    timpaik  
       321 天前
    约定俗成,标准库里直接可以认为这俩互斥,但没有类型系统保证,第三方库保险起见看看实现就好了
    realpg
        24
    realpg  
       321 天前
    golang 提供的官方标准库里,出现了你设想的那种场景,那就是 bug ,golang 官方负责解决,你下层不用想能解决上层的问题。

    你引用了的别人的三方库里出现这种问题,那是哪个库作者的 bug ,库作者负责解决这种问题,你下层不用想能解决上层的问题。
    Assassinrx
        25
    Assassinrx  
    OP
       319 天前
    @timpaik ok ,了解
    Assassinrx
        26
    Assassinrx  
    OP
       319 天前
    @realpg 确实是这个道理
    lotusgrm
        27
    lotusgrm  
       276 天前
    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
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   960 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 22:19 · PVG 06:19 · LAX 15:19 · JFK 18:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.