go进程独占文件的实现,可用于单进程锁等其它逻辑

go进程独占文件的实现,可用于单进程锁等其它逻辑

Tony哥
2023-10-20 / 1 评论 / 92 阅读 / 正在检测是否收录...
在网上搜了一大圈,找到了一个独占文件的逻辑用了下,发出来和大家分享一下,写的还是不错的,我试了其它的一些方法,比如说 _, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, os.ModeExclusive) 这些乱起八糟的说明还是不能行,结果这套代码可以,那么就分享一下吧!

好吧直接上代码

package main

import (
    "flag"
    "fmt"
    "os"
    "syscall"
    "time"
)

var filename string
var openSec int64

func main() {
    flag.Int64Var(&openSec, "openSec", 60, "独占的秒数")
    flag.StringVar(&filename, "filename", "D:/dd.txt", "需要独占打开得文件")
    flag.Parse()
    lockFile(filename, openSec)
}


func lockFile(filename string, openSec int64) error {
    _, err := os.Stat(filename)
    if err != nil {
        return fmt.Errorf("打开文件[%s]失败,%v", filename, err)
    }


    p, err := syscall.UTF16PtrFromString(filename)
    if err != nil {
        return err
    }
    fd, err := syscall.CreateFile(p,
        syscall.GENERIC_READ|syscall.GENERIC_WRITE,
        0,
        nil,
        syscall.OPEN_EXISTING, // syscall.CREATE_ALWAYS
        syscall.FILE_ATTRIBUTE_NORMAL,
        0,
    )
    if err != nil {
        return err
    }
    time.Sleep(time.Second * time.Duration(openSec))
    syscall.Close(fd)
    return nil
}

以上代码是别的写的,那么我拿他来做了个函数封装,用于我的程序单进程锁

其实下面这些封装是不够完美的,相当于跑了一个独立线程来锁死文件,由于go还是不怎么熟练先凑合用了,如果你有更合适的方案欢迎发过来一起学习一下
func main() {

    executablePath, _ := os.Executable()
    path = filepath.Dir(executablePath)

    if !lockProcess() {
        s := "仅能执行一个进程"
        writeToLogFile(s)
        fmt.Println(s)
        return
    }
    // 业务逻辑...
 }
 // 判断是否与其它实例并行
func lockProcess() bool {
    filePath := filepath.Join(path, ".lock")
    file, err := os.OpenFile(filePath, os.O_CREATE, 0666)
    if err != nil {
        return false
    }
    file.Close()
    go func() {
        err := lockFile(filePath)
        if err != nil {
            return
        }
        for {
            time.Sleep(time.Hour * 1000)
        }
    }()
    return true
}

func lockFile(filename string) error {
    _, err := os.Stat(filename)
    if err != nil {
        return fmt.Errorf("打开文件[%s]失败,%v", filename, err)
    }
    p, err := syscall.UTF16PtrFromString(filename)
    if err != nil {
        return err
    }
    _, err = syscall.CreateFile(p,
        syscall.GENERIC_READ|syscall.GENERIC_WRITE,
        0,
        nil,
        syscall.OPEN_EXISTING, // syscall.CREATE_ALWAYS
        syscall.FILE_ATTRIBUTE_NORMAL,
        0,
    )
    if err != nil {
        return err
    }
    return nil
  }
0

评论 (1)

取消
  1. 头像
    孤岛
    MacOS · Google Chrome

    表情

    回复