go语言实现的一个高效,轻量级的文件锁 gflock

在我们对文件进行操作的时候, 如果你不需要你操作的文件被其他协程访问,则就需要使用一个文件锁来对我们操作的文件进行加锁,今天给大家推荐的这个gflock使用也非常简单:

首先安装依赖: 

go get -u github.com/tekitian/gflock

使用示例 

import "github.com/tekitian/gflock"

fileLock := gflock.New("/var/lock/go-lock.lock")

locked, err := fileLock.TryLock()

if err != nil {
	// handle locking error
}

if locked {
	// do work
	fileLock.Unlock()
}

github仓库地址 https://github.com/tekintian/gflock

一个二次封装的文件/文件夹锁使用示例

filelock.go

package internal

import (
    "fmt"
    "log"
    "os"
    "path/filepath"

    "github.com/tekitian/gflock"
)

// FileLock provides a file lock mechanism based on gflock.
type FileLock struct {
    lock    *gflock.GFlock
    verbose bool
}

// NewFileLock creates a new instance of FileLock.
func NewFileLock(path string, verbose bool) (*FileLock, error) {
    err := os.MkdirAll(filepath.Dir(path), 0o750)
    if err != nil {
        return nil, fmt.Errorf("creating lock file directory: %w", err)
    }

    if verbose {
        log.Printf("Initializing file lock at %s", path)
    }

    return &FileLock{
        lock:    flock.New(path),
        verbose: verbose,
    }, nil
}

// Release unlocks the file lock.
func (f *FileLock) Release() error {
    if err := f.lock.Unlock(); err != nil {
        return fmt.Errorf("releasing file lock at %s: %w", f.lock.Path(), err)
    }
    if f.verbose {
        log.Printf("Lock file %s successfully released", f.lock.Path())
    }
    return nil
}

// Acquire tries to acquire a file lock.
// It is possible for multiple goroutines within the same process
// to acquire the same lock, so acquireLock is not thread safe in
// that sense, but protects access across different processes.
func (f *FileLock) Acquire() error {
    ok, err := f.lock.TryLock()
    if err != nil {
        return fmt.Errorf("acquiring file lock at %s: %w", f.lock.Path(), err)
    }
    if !ok {
        return fmt.Errorf("lock %s already acquired by another process", f.lock.Path())
    }
    if f.verbose {
        log.Printf("Acquired lock file at %s", f.lock.Path())
    }
    return nil
}

测试用例

需要安装增强测试包 got get github.com/stretchr/testify

filelock_test.go

package internal

import (
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/require"
)

// TestAcquireFileLock tests that a lock can be acquired multile times
// within a same process.
func TestAcquireFileLock(t *testing.T) {
	tempDir := t.TempDir()

	fl, err := NewFileLock(filepath.Join(tempDir, ".myapp.lock"), false)
	require.NoError(t, err)
	defer func() {
		err := fl.Release()
		require.NoError(t, err)
	}()

	// acquire lock
	err = fl.Acquire()
	require.NoError(t, err)
	require.True(t, fl.lock.Locked())

	// acquiring lock a second time within the same process
	// should succeed
	err = fl.Acquire()
	require.NoError(t, err)
	require.True(t, fl.lock.Locked())

	// release lock
	err = fl.Release()
	require.NoError(t, err)
	require.False(t, fl.lock.Locked())

	// acquire a released lock
	err = fl.Acquire()
	require.NoError(t, err)
	require.True(t, fl.lock.Locked())
}

  • 22
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值