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

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

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

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

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

    你引用了的别人的三方库里出现这种问题,那是哪个库作者的 bug ,库作者负责解决这种问题,你下层不用想能解决上层的问题。
    Assassinrx
        25
    Assassinrx  
    OP
       2023-06-12 13:47:56 +08:00
    @timpaik ok ,了解
    Assassinrx
        26
    Assassinrx  
    OP
       2023-06-12 13:49:00 +08:00
    @realpg 确实是这个道理
    lotusgrm
        27
    lotusgrm  
       2023-07-25 17:10:29 +08:00
    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     Solana     5270 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 09:11 PVG 17:11 LAX 02:11 JFK 05:11
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86