如何在Go语言中获得文件的独占锁

24

我应该如何在go语言中获得一个独占式的读取文件权限? 我已经尝试过文档,但仍然可以在记事本中打开文件并进行编辑。 我想在第一个进程没有明确关闭它之前,否决任何其他进程访问它以进行读写操作。在.NET中,我可以这样做:

File.Open("a.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.None);

我该如何使用Go语言实现它?


4
这个功能取决于所使用的文件系统,Go语言无法保证其可用性。 - Volker
1
没有“Microsoft”标签,但这个问题特别针对在微软操作系统上使用Go语言。 - Vorsprung
1个回答

20

我终于找到了一个可以锁定文件的go包。

这是该仓库: https://github.com/juju/fslock

go get -u github.com/juju/fslock

这个软件包完全符合其描述。

fslock是基于文件锁的跨进程互斥锁,在Windows和*nix平台上均可使用。在Windows上,fslock依赖LockFileEx,在*nix系统上则依赖flock。超时功能在Windows上使用重叠I/O,但在*nix平台上,超时需要使用一个 goroutine ,该 goroutine 将一直运行,直到获取到锁,无论超时。如果需要避免使用 goroutines,请轮询TryLock并循环执行。

要使用此软件包,首先为锁文件创建一个新锁。

func New(filename string) *Lock

如果锁定文件不存在,此API将创建锁定文件。

然后我们可以使用锁定句柄来锁定(或尝试锁定)文件

func (l *Lock) Lock() error

上述函数还有一个超时版本,它会尝试获取文件锁直到超时

func (l *Lock) LockWithTimeout(timeout time.Duration) error

最后,如果你完成了任务,需要通过以下方式释放已获得的锁定:

Finally, if you are done, release the acquired lock by

func (l *Lock) Unlock() error

非常基本的实现

package main

import (
    "time"
    "fmt"
    "github.com/juju/fslock"
)

func main() {
    lock := fslock.New("../lock.txt")
    lockErr := lock.TryLock()
    if lockErr != nil {
        fmt.Println("falied to acquire lock > " + lockErr.Error())
        return
    }

    fmt.Println("got the lock")
    time.Sleep(1 * time.Minute)

    // release the lock
    lock.Unlock()
}

2
请不要删除此答案。这是为了以后可能需要执行此类似工作的人编写的。我花了很多小时搜索这个包。 - Vishal Anand
2
你的程序包在Unix上使用flock()进行锁定,因此不提供操作系统级别的强制锁定。 - Vorsprung
3
我认为这个包存在问题,因为自2016年以来代码没有进行任何修改。如果作者是Donald Knuth,我会说这没问题,但显然Go社区对此也有一些想法:https://go.googlesource.com/proposal/+/master/design/33974-add-public-lockedfile-pkg.md - Konrad Kleine
1
@KonradKleine 你真是救星啊。我们一直在使用“github.com/nightlyone/lockfile”时遇到问题,我不确定这个库是否有bug或者是我的问题。这个库提供的保证并不清晰,其他几个库也让我感到有些不安。很高兴Go团队对此有官方线程。 :) - Sam Claus
3
在商业闭源的golang项目中使用LGPL许可证的库并不是一个好的选择,详情请参见此处:https://www.makeworld.space/2021/01/lgpl_go.html。有一种替代方案是使用BSD-3许可证的库:https://github.com/gofrs/flock。 - Ezequiel Muns
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接