You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go中使用flock锁定路径后os.Stat无法正确检测文件存在性

问题根因

该现象是Go生态常用的gofrs/flock库默认行为导致的:调用Lock()方法对不存在的路径加锁时,库会默认携带文件创建标记,自动在目标路径生成空文件后再加锁。因此加锁完成后再执行os.Stat()检测时,文件已经被flock创建,自然不会返回文件不存在的错误。
另外你贴的代码里存在一处笔误:os.IsNotExist(errs)传入的变量名错误,应该传入前面接收到的err变量,该笔误也会导致错误分支判断失效。

可行解决思路
  • 方案1:加锁时关闭自动创建文件的配置
    不要直接调用无参数的Lock()方法,改用支持自定义锁标记的加锁接口,去掉自动创建文件的LOCK_CREATE标记,文件不存在时加锁操作会直接返回对应错误,你可以在加锁阶段就捕获文件不存在的场景:
    filePath := filepath.Join(r.path, fmt.Sprintf("%s_event.json", eventId))
    fileLock := flock.New(filePath)
    // 仅加排他锁,不自动创建不存在的文件
    err := fileLock.Lock(syscall.LOCK_EX)
    if err != nil {
        if os.IsNotExist(err) {
            return event, EventNotFound{}
        }
        return
    }
    defer fileLock.Close()
    
    // 加锁成功后文件必然存在,可直接执行业务逻辑
    
  • 方案2:加锁后校验文件属性识别自动创建的空文件
    如果你需要兼容现有加锁逻辑,可以在加锁后通过文件属性判断是否为flock自动生成的空文件,识别到该场景时清理残留空文件再返回不存在错误:
    filePath := filepath.Join(r.path, fmt.Sprintf("%s_event.json", eventId))
    fileLock := flock.New(filePath)
    fileLock.Lock()
    defer fileLock.Close()
    
    fileInfo, err := os.Stat(filePath)
    if err != nil {
        if os.IsNotExist(err) {
            return event, EventNotFound{}
        }
        return
    }
    // flock自动创建的文件大小为0,无业务写入内容,判定为原文件不存在
    if fileInfo.Size() == 0 {
        os.Remove(filePath) // 清理自动生成的垃圾文件
        return event, EventNotFound{}
    }
    // 后续正常处理已有文件的业务逻辑
    

注意:优先选择方案1,方案2存在极小的概率把业务正常生成的0字节文件误判为不存在,适合业务逻辑中不会生成0字节事件文件的场景使用。

内容的提问来源于stack exchange,提问作者Maryam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.08 16:15:17