在我们对文件进行操作的时候, 如果你不需要你操作的文件被其他协程访问,则就需要使用一个文件锁来对我们操作的文件进行加锁,今天给大家推荐的这个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 workfileLock.Unlock()
}
github仓库地址 https://github.com/tekintian/gflock
一个二次封装的文件/文件夹锁使用示例
filelock.go
package internalimport ("fmt""log""os""path/filepath""github.com/tekitian/gflock"
)// FileLock provides a file lock mechanism based on gflock.
type FileLock struct {lock *gflock.GFlockverbose 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 internalimport ("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 lockerr = fl.Acquire()require.NoError(t, err)require.True(t, fl.lock.Locked())// acquiring lock a second time within the same process// should succeederr = fl.Acquire()require.NoError(t, err)require.True(t, fl.lock.Locked())// release lockerr = fl.Release()require.NoError(t, err)require.False(t, fl.lock.Locked())// acquire a released lockerr = fl.Acquire()require.NoError(t, err)require.True(t, fl.lock.Locked())
}